머신러닝을 통해 손글씨 숫자 인식하기, 언어 판별 프로그램을 만들었다.
아무래도 무작정 따라하는 것 보다는 안의 내용을 알아가면서 해보고 싶어서 주석을 최대한 달아볼 계획이다.
차후에 각 내용을 수행하기 위한 자세한 내용을 추가할 예정이다.
여기 나오는 내용은 "파이썬을 이용한 머신러닝, 딥러닝, 실전 개발 입문"에 나오는 내용이다.
===================== Python =====================
### 손글씨 숫자 인식하기
# 파일 다운로드 받아 저장하기
import urllib.request as req
import gzip, os, os.path
savepath = "./mnist" # .은 Pycharm 최상위 폴더인 deep1을 뜻한다.
baseurl = "http://yann.lecun.com/exdb/mnist"
files = [
"train-images-idx3-ubyte.gz",
"train-labels-idx1-ubyte.gz",
"t10k-images-idx3-ubyte.gz",
"t10k-labels-idx1-ubyte.gz"]
# 다운로드
if not os.path.exists(savepath): # 저장 장소가 존재하지 않는다면 True로 나온다.
os.mkdir(savepath) # 저장 장소가 존재하지 않으면 실행되어 폴더를 만든다.
for f in files:
url = baseurl + "/" + f
loc = savepath + "/" + f
print("download:", url)
if not os.path.exists(loc): # 저장 장소에 files 명칭으로 된 파일이 존재하지 않으면 True로 나온다.
req.urlretrieve(url, loc) # 저장 장소에 files 명칭으로 된 파일이 존재하지 않으면 파일을 다운받는다.
# GZip 압축 해제
for f in files:
gz_file = savepath + "/" + f
raw_file = savepath + "/" + f.replace(".gz", "") # 이 과정을 거치면 .gz가 사라진다.
print("gzip:", f)
with gzip.open(gz_file, "rb") as fp: # gzip을 이용해서 .gz파일을 body 객체에 담아준다.
body = fp.read()
with open(raw_file, "wb") as w: # 위에서 압축이 해제된 파일을 .gz를 떼어낸 명칭으로 파일을 생성한다.
w.write(body)
print("ok")
### 이미지 데이터를 바이너리 데이터로 변환하고 csv로 바꾸기
import struct
open().r
def to_csv(name, maxdata):
# 레이블 파일과 이미지 파일 열기
lbl_f = open("./mnist/" + name + "-labels-idx1-ubyte", "rb") # 어떤 숫자가 적혀있는지 나타내는 labels
img_f = open("./mnist/" + name + "-images-idx3-ubyte", "rb") # 이미지 정보가 저장된 images
csv_f = open("./mnist/" + name + ".csv", "w", encoding="utf-8") # 우리가 이미지를 csv로 저장할 파일
# 헤더 정보 읽기 https://m.blog.naver.com/cylover0429/220595086136
mag, lbl_count = struct.unpack(">II", lbl_f.read(8)) # >는 big-endian, 대문자 i는 unsigned int
# 결과는 (2049, 60000). 각각에 저장된다.
mag, img_count = struct.unpack(">II", img_f.read(8)) # .read(8)은 8개만 읽겠다는 뜻. 여기서는 buffer이므로
# 결과는 (2051, 60000). 각각에 저장된다.
rows, cols = struct.unpack(">II", img_f.read(8)) # 8씩 읽어서 각 객체에 저장하게 된다.
# 결과는 (28, 28). 각각에 저장된다.
pixels = rows * cols # 픽셀 크기 지정. 28 * 28
# 이미지 데이터를 읽고 CSV로 저장하기
res = []
for idx in range(lbl_count):
if idx > maxdata: # for문 끝을 지정. 인덱스가 전체 데이터보다 많아지면 종료.
break
label = struct.unpack("B", lbl_f.read(1))[0] # B는 unsigned char를 뜻한다.
'''
(5,)
(0,)
(4,)
(1,)
(9,)
(2,)
...
형태의 결과가 나오게 되는데 이걸 앞에 있는 값만 뽑아내기 위해서 [0]을 붙인다.
'결과'
5
0
4
1
9
2
'''
bdata = img_f.read(pixels) # 28 * 28 만큼 img_f를 읽어서 bdata에 저장한다.
sdata = list(map(lambda n: str(n), bdata))
csv_f.write(str(label) + ",")
csv_f.write(",".join(sdata) + "\r\n")
# 잘 저장됐는지 이미지 파일로 저장해서 테스트하기
if idx < 10:
s = "P2 28 28 255\n"
s += " ".join(sdata)
iname = "./mnist/{0}-{1}-{2}.pgm".format(name, idx, label)
with open(iname, "w", encoding="utf-8") as f:
f.write(s)
csv_f.close()
lbl_f.close()
img_f.close()
# 결과를 파일로 출력하기
to_csv("train", 1000)
to_csv("t10k", 500)
### 위에서 얻어진 csv파일을 이용해서 머신러닝을 하여 정답률이 얼마나 나오는지 확인한다.
from sklearn import model_selection, svm, metrics
# CSV 파일을 읽어 들이고 가공하기
def load_csv(fname):
labels = []
images = []
with open(fname, "r") as f:
for line in f:
cols = line.split(",")
if len(cols) < 2: continue
labels.append(int(cols.pop(0)))
vals = list(map(lambda n: int(n) / 256, cols))
images.append(vals)
return {"labels":labels, "images":images}
data = load_csv("./mnist/train.csv")
test = load_csv("./mnist/t10k.csv")
# 학습하기
clf = svm.SVC()
clf.fit(data["images"], data["labels"])
# 예측하기
predict = clf.predict(test["images"])
# 결과 확인하기
ac_score = metrics.accuracy_score(test["labels"], predict)
cl_report = metrics.classification_report(test["labels"], predict)
print("정답률 =", ac_score)
print("리포트 =")
print(cl_report)
### 파이썬을 이용해서 서버 만들기.
import http.server
httpcall = http.server.HTTPServer(('127.0.0.1', 8080), http.server.SimpleHTTPRequestHandler)
httpcall.serve_forever()
### 언어 판별 프로그램 만들기
from sklearn import svm, metrics
import glob, os.path, re, json
# 텍스트를 읽어 들이고 출현 빈도 조사하기
def check_freq(fname):
name = os.path.basename(fname)
lang = re.match(r'^[a-z]{2,}', name).group()
with open(fname, "r", encoding="utf-8") as f:
text = f.read()
text = text.lower() # 소문자 변환
# 숫자 세기 변수(cnt) 초기화하기
cnt = [0 for n in range(0, 26)]
code_a = ord("a")
code_z = ord("z")
# 알파벳 출현 횟수 구하기
for ch in text:
n = ord(ch)
if code_a <= n <= code_z: # a~z 사이에 있을 때
cnt[n - code_a] += 1
# 정규화하기
total = sum(cnt)
freq = list(map(lambda n: n / total, cnt))
return (freq, lang)
# 각 파일 처리하기
def load_files(path):
freqs = []
labels = []
file_list = glob.glob(path)
for fname in file_list:
r = check_freq(fname)
freqs.append(r[0])
labels.append(r[1])
return {"freqs": freqs, "labels": labels}
data = load_files("./lang/train/*.txt")
test = load_files("./lang/test/*.txt")
# 이후를 대비해서 JSON으로 결과 저장하기
with open("./lang/freq.json", "w", encoding="utf-8") as fp:
json.dump([data, test], fp)
# 학습하기
clf = svm.SVC()
clf.fit(data["freqs"], data["labels"])
# 예측하기
predict = clf.predict(test["freqs"])
# 결과 테스트하기
ac_score = metrics.accuracy_score(test["labels"], predict)
cl_report = metrics.classification_report(test["labels"], predict)
print("정답률 =", ac_score)
print("리포트 =")
print(cl_report)
===================== Python =====================
'프로그래밍 > Python, R 프로그래밍' 카테고리의 다른 글
[Python] 파이썬을 이용한 여러가지 플롯 그리기 (0) | 2018.07.29 |
---|---|
[Python] Python 28일차(파이썬을 이용한 머신러닝, 딥러닝 실전 개발 입문) (0) | 2018.07.16 |
[Python] matplotlib 라이브러리에서 한글 폰트가 깨지지 않게 만드는 방법 (0) | 2018.07.10 |
[Python] Python 26일차(파이썬을 이용한 머신러닝, 딥러닝 실전 개발 입문) (0) | 2018.07.10 |
[Python] Python 25일차(파이썬을 이용한 머신러닝, 딥러닝 실전 개발 입문) (0) | 2018.07.09 |