今回は、前回CSVに変換したMNISTの手書き文字画像を、0〜9に分類しました。
機械学習の一大テーマである画像分類の復習です。
今回も Pythonによるスクレイピング&機械学習開発テクニック増補改訂 Scrapy、BeautifulSoup、scik [ クジラ飛行机 ]の第4章を参考にさせていただきながら、取り組んでいます。
MNISTのデータのCSVへの変換は、前回の記事をご参照ください。
では、振り返っていきたいと思います。
コード全体は以下の通りで、「mnist-train.py」に保存しました。 今回は、「load_csv」という関数を定義して、CSVデータを読み込んで学習時に都合がいいように説明変数のデータ(imagesデータ)と目的変数のデータ(labelsデータ)に読み込んでいます。 from sklearn import svm,metrics #(1)CSVファイルを読み込んで訓練データに変換 #(2)訓練データで学習する #(3)テストデータで予測する #(4)精度を確認する では、コードを順番に見ていきます。 まず、「load_csv」の関数の中身を見ていきます。 最初に、画像データとラベルデータを格納するリスト型の変数(images,labels)を初期化します。 def load_csv(fname): 関数の引数で渡したファイル名でファイルを開きます。 (今回はCSVファイルになります。) with open(fname, 'r') as f: 開いたファイルから一行ずつ読み込んで、split()を使って読み込んだ行を','で分割します。1行のデータは、1画像ずつ、ラベルと、画像のセットになっています。詳しくは、CSVへの変換の記事をご参照ください。 for line in f: 分割した結果、2個未満の場合は、次の行にスキップします。 if len(cols) < 2 : continue pop()をつかって最初の要素をlabelsに追加します。 labels.append(int(cols.pop(0))) lambda式とmap関数をつかって、画像データの各画素値を256で割った0〜1の間の値に標準化します。 vals = list(map(lambda n:int(n) / 256, cols)) 標準化したデータをimagesに追加します。 images.append(vals) 全行に対して処理を行ったら最後に、辞書型のデータとしてimagesとlabelsを返します。 return {'labels':labels, 'images':images} 定義したload_csv関数で、訓練データ(train.csv)とテストデータ(t10k.csv)を読み込んで学習用のdataとtestに変換します。 data = load_csv('./mnist/train.csv') scikit-learnからインポートしたsvm(サポートベクターマシン)のモジュールから、SVC(Support Vector Classification)のクラスを呼び出して、サポートベクターマシンを使った分類ができるモデルの実体を作ります。 モデルの実体ができたら、あとは、fit()メソッドを使って、訓練データ(data['images'])と正解ラベル(data['labels'])を引数に渡して実行するだけで、学習は完了です clf.fit(data['images'],data['labels']) 学習したモデル(clf)を使って、予測を行います。 予測についても学習と同様に簡単で、predict()メソッドに検証データ(test['images'])を渡すことで、予測した結果を出力してくれます。 predict = clf.predict(test['images']) 予測した結果(predict)の精度を算出します。 まず、scikit-learnからmetricsモジュールをimportして、accuracy_score()メソッドを使って全体の精度を求めます。 accuracy_score()は、検証データの正解ラベル(test['labels'])と予測した結果(predict)を引数に渡す事で、予測した結果が正解ラベルと同じだった割合を算出してくれます。 ac_score = metrics.accuracy_score(test['labels'], predict) また、scikit-learnからmetricsモジュールの、classification_report()メソッドを使ってラベル毎の精度を求めます。 cl_score = metrics.classification_report(test['labels'], predict) 最後に、求めた全体の精度と、ラベル毎の精度を出力します。 print('正解率:',ac_score) 先ほど作成したファイルを実行してみます。 python3 mnist-train.py 以下の通り、MNISTの手書き文字画像のCSVデータを読み込んで、0~9に分類し、その精度を出力することができました。 今回は、手書き文字の画像データMNISTをSVMで0~9のどの数字かを分類するモデルを作ることができました。 ほとんど何も調整せず、 たった1,000枚の数字を学習させただけで、全体で88%の正解率です。 「1」に至っては、ほとんど間違うことなく正解していました。 次回は、機械学習のもう一つのテーマ「自然言語」を扱ったテーマに取り組みたいと思います。 今後も、Pythonによるスクレイピング&機械学習開発テクニック増補改訂 Scrapy、BeautifulSoup、scik [ クジラ飛行机 ]で、スクレイピングと機械学習開発に取り組んでいきたいと思います。 【過去記事】 2019年8月31日(土)にE資格を受験して、合格しました! E資格対策として勉強の進め方や、参考書などをまとめました。 これから受験される方がいらっしゃいましたらご参考まで。 2019年3月9日(土)にG検定を受験し、見事合格できました! 受験の体験記や勉強法などを別のブログにまとめました。 これから受験される方がいらっしゃいましたらご参考まで。 【E資格対策に使った参考書】 SVMでMNISTのデータを画像分類する
1.全体像
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_score = metrics.classification_report(test['labels'], predict)
print('正解率:',ac_score)
print('レポート:')
print(cl_score)2.CSVファイルを読み込んで訓練データに変換
labels= [ ]
images= [ ]
cols = line.split(',')
test = load_csv('./mnist/t10k.csv')3.訓練データで学習する
4.テストデータで予測する
5.精度を確認する
print('レポート:')
print(cl_score) 6.コマンドラインから実行してみる