머신러닝을 통해 손글씨 숫자 인식하기, 언어 판별 프로그램을 만들었다.

아무래도 무작정 따라하는 것 보다는 안의 내용을 알아가면서 해보고 싶어서 주석을 최대한 달아볼 계획이다.

차후에 각 내용을 수행하기 위한 자세한 내용을 추가할 예정이다.

여기 나오는 내용은 "파이썬을 이용한 머신러닝, 딥러닝, 실전 개발 입문"에 나오는 내용이다.






===================== 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 =====================

+ Recent posts