戻る
■TensorFlow+Keras(ディープラーニング)でカタカナを判定
■文字データベースのダウンロード etlcdb http://etlcdb.db.aist.go.jp/?lang=ja 画面上部の「DOWNLOAD」から利用申請できる 申請すると、すぐにメールアドレスにダウンロードリンクとパスワードが送られてくる 今回はダウンロードページから「ETL-1」をダウンロードする ダウンロードしたファイルを展開すると、「ETL-1」というフォルダの中に14個のファイルが作成される ■データベースを画像に変換
# ETL1Cのファイルを読み込む import struct from PIL import Image, ImageEnhance import glob, os # 出力ディレクトリ outdir = "png-etl1/" if not os.path.exists(outdir): os.mkdir(outdir) # ETL1ディレクトリ以下のファイルを処理する files = glob.glob("ETL1/*") for fname in files: if fname == "ETL1/ETL1INFO": continue # 情報ファイルは飛ばす print(fname) # ETL1のデータファイルを開く f = open(fname, 'rb') f.seek(0) while True: # メタデータ+画像データの組を一つずつ読む s = f.read(2052) if not s: break # バイナリデータなのでPythonが理解できるように抽出 r = struct.unpack('>H2sH6BI4H4B4x2016s4x', s) code_ascii = r[1] code_jis = r[3] # 画像データとして取り出す iF = Image.frombytes('F', (64, 63), r[18], 'bit', 4) iP = iF.convert('L') # 画像を鮮明にして保存 dir = outdir + "/" + str(code_jis) if not os.path.exists(dir): os.mkdir(dir) fn = "{0:02x}-{1:02x}{2:04x}.png".format(code_jis, r[0], r[2]) fullpath = dir + "/" + fn #if os.path.exists(fullpath): continue enhancer = ImageEnhance.Brightness(iP) iE = enhancer.enhance(16) iE.save(fullpath, 'PNG') print("ok")
■画像をリサイズしてバイナリにまとめる
import glob import numpy as np import cv2 import matplotlib.pyplot as plt import pickle # 保存先や画像サイズの指定 out_dir = "./png-etl1" # 画像データがあるディレクトリ im_size = 25 # 画像サイズ save_file = out_dir + "/katakana.pickle" # 保存先 plt.figure(figsize=(9, 17)) # 出力画像を大きくする # カタカナの画像が入っているディレクトリから画像を取得 kanadir = list(range(177, 220+1)) kanadir.append(166) # ヲ kanadir.append(221) # ン result = [] for i, code in enumerate(kanadir): img_dir = out_dir + "/" + str(code) fs = glob.glob(img_dir + "/*") print("dir=", img_dir) # 画像を読み込んでグレイスケールに変換しリサイズする for j, f in enumerate(fs): img = cv2.imread(f) img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img = cv2.resize(img_gray, (im_size, im_size)) result.append([i, img]) # Jupyter Notebookで画像を出力 if j == 3: plt.subplot(11, 5, i + 1) plt.axis("off") plt.title(str(i)) plt.imshow(img, cmap='gray') # メモリ消費対策に読み込む数を制限 #print(str(j) + ' / ' + f) if j >= 99: break # ラベルと画像のデータを保存 pickle.dump(result, open(save_file, "wb")) plt.show() # 画像に保存する plt.savefig("output.png") print("ok")
■多層パーセプトロン(Multilayer perceptron)で学習
import numpy as np import cv2, pickle from sklearn.model_selection import train_test_split import keras # データファイルと画像サイズの指定 data_file = "./png-etl1/katakana.pickle" im_size = 25 in_size = im_size * im_size out_size = 46 # ア-ンまでの文字の数 # 保存した画像データ一覧を読み込む data = pickle.load(open(data_file, "rb")) # 画像データを0-1の範囲に直す y = [] x = [] for d in data: (num, img) = d img = img.reshape(-1).astype('float') / 255 y.append(keras.utils.np_utils.to_categorical(num, out_size)) x.append(img) x = np.array(x) y = np.array(y) # 学習用とテスト用に分離する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True) # モデル構造を定義 Dense = keras.layers.Dense model = keras.models.Sequential() model.add(Dense(512, activation='relu', input_shape=(in_size,))) model.add(Dense(out_size, activation='softmax')) # モデルをコンパイルして学習を実行 model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) model.fit(x_train, y_train, batch_size=20, epochs=50, verbose=1, validation_data=(x_test, y_test)) # モデルを評価 score = model.evaluate(x_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0])
正解率= 0.6391304135322571 loss= 1.788340950012207 ※読み込む画像を100に制限しているので、正解率は低い ■畳み込みニューラルネットワーク(Convolutional Neural Network)で学習
import numpy as np import cv2, pickle from sklearn.model_selection import train_test_split import keras from keras.models import Sequential from keras.models import load_model from keras.layers import Dense, Dropout, Flatten from keras.layers import Conv2D, MaxPooling2D from keras.optimizers import RMSprop from keras.datasets import mnist import matplotlib.pyplot as plt # データファイルと画像サイズの指定 data_file = "./png-etl1/katakana.pickle" im_size = 25 out_size = 46 # ア-ンまでの文字の数 im_color = 1 # 画像の色空間/グレイスケール in_shape = (im_size, im_size, im_color) # カタカナ画像のデータセットを読み込む data = pickle.load(open(data_file, "rb")) # 画像データを変形して0-1の範囲に直す y = [] x = [] for d in data: (num, img) = d img = img.astype('float').reshape(im_size, im_size, im_color) / 255 y.append(keras.utils.np_utils.to_categorical(num, out_size)) x.append(img) x = np.array(x) y = np.array(y) # 学習用とテスト用に分離する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True) ## CNNモデル構造を定義 #model = Sequential() #model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=in_shape)) #model.add(Conv2D(64, (3, 3), activation='relu')) #model.add(MaxPooling2D(pool_size=(2, 2))) #model.add(Dropout(0.25)) # #model.add(Flatten()) #model.add(Dense(128, activation='relu')) #model.add(Dropout(0.5)) # #model.add(Dense(out_size, activation='softmax')) #model.compile( # loss='categorical_crossentropy', # optimizer=RMSprop(), # metrics=['accuracy']) # ## モデルを保存 #model.save('katakana_cnn-model.h5') # モデルを読み込み model = load_model('katakana_cnn-model.h5') ## 学習を実行して評価 #hist = model.fit(x_train, y_train, # batch_size=128, # epochs=12, # verbose=1, # validation_data=(x_test, y_test)) # ## 学習結果を保存 #model.save_weights('katakana_cnn-weight.h5') # 学習結果を読み込み model.load_weights('katakana_cnn-weight.h5') # モデルを評価 score = model.evaluate(x_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0])
正解率= 0.7630434632301331 loss= 0.9600743656573089 ※読み込む画像を100に制限しているので、正解率は低い それでも多層パーセプトロンよりは向上している ※読み込む画像は800まで耐えられた 800の画像をもとに判定すると、正解率は以下になった 正解率= 0.9686141014099121 loss= 0.12908870187871482 ■畳み込みニューラルネットワーク(Convolutional Neural Network)の学習結果から画像を判定
import numpy as np import cv2, pickle from sklearn.model_selection import train_test_split import keras from keras.models import Sequential from keras.models import load_model from keras.optimizers import RMSprop from keras.datasets import mnist import matplotlib.pyplot as plt # データファイルと画像サイズの指定 data_file = "./png-etl1/katakana.pickle" im_size = 25 out_size = 46 # ア-ンまでの文字の数 im_color = 1 # 画像の色空間/グレイスケール in_shape = (im_size, im_size, im_color) # カタカナ画像のデータセットを読み込む data = pickle.load(open(data_file, "rb")) # 画像データを変形して0-1の範囲に直す y = [] x = [] for d in data: (num, img) = d img = img.astype('float').reshape(im_size, im_size, im_color) / 255 y.append(keras.utils.np_utils.to_categorical(num, out_size)) x.append(img) x = np.array(x) y = np.array(y) # 学習用とテスト用に分離する x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, train_size = 0.8, shuffle = True) # モデルを読み込み model = load_model('katakana_cnn-model.h5') # 学習結果を読み込み model.load_weights('katakana_cnn-weight.h5') # モデルを評価 score = model.evaluate(x_test, y_test, verbose=1) print('正解率=', score[1], 'loss=', score[0])