csv_Functionsモジュールの実装|Excel VBAでMNIST機械学習

本ページでは実際に自身の描いた手描き文字の識別を行うための準備を行います。
手書き文字をニューラルネットワークに読み込ませるには、MNISTデータと同じように入力データ(手書き文字データ)を28×28の計784個の数値に変換する必要があります。
というわけで、ここでは選択したbmpファイルを読み込み、数値として変換するための「csv_Functions」というモジュールを実装していきます。
本ページからはニューラルネットワークによる推論フェーズの内容です。
ニューラルネットワークの実装ができていない方はメインページの「ニューラルネットワーク作成編」を参考にニューラルネットワークの実装を先に行ってください。
csv_Functionsモジュールの実装
まずは標準モジュールで「csv_Functions」というモジュールを作成します。
ニューラルネットワーク作成編で実装したっモジュールは「Option Base 1」を使っていましたが、ここでは使わないので注意して下さい。
以下はcsv_Functionsモジュールの全コードです。
'VBA csv_Functions(module)
Option Explicit
'――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Function bmp_to_csv() As Long()
Application.ScreenUpdating = False
Dim FilePath As Variant
FilePath = Application.GetOpenFilename
If FilePath = False Then
End
End If
Dim FileSize As Long
FileSize = FileLen(FilePath)
If FileSize = 0 Then
MsgBox "選択したファイルは有効ではありません。"
Exit Function
End If
Dim FileID As Integer
FileID = FreeFile
Open FilePath For Binary As #FileID
Dim BinaryData() As Byte
ReDim BinaryData(0 To FileSize - 1)
Get #FileID, , BinaryData
Close #FileID
If Not (BinaryData(0) = 66 And BinaryData(1) = 77) Then
MsgBox "bmp画像を選択してください。"
Exit Function
End If
'バイナリデータからピクセル値データのみを抜き取る
Dim i As Long
Dim Data() As Long
Dim RGBData() As Long
Dim GrayData() As Long
ReDim Data(UBound(BinaryData) - 53)
ReDim RGBData(UBound(BinaryData) - 53) 'NNで使うため配列の1番目から値を格納(0番目は空にする)
For i = 1 To UBound(RGBData)
RGBData(i) = BinaryData(i + 53)
Next i
'RGBデータをグレースケールデータに変換(学習データと入力値を揃える)
ReDim GrayData(UBound(RGBData) / 3) '0番目は空にする
For i = 1 To UBound(GrayData)
GrayData(i) = Abs((RGBData((i - 1) * 3 + 1) * 0.11 + _
RGBData((i - 1) * 3 + 1 + 1) * 0.59 + _
RGBData((i - 1) * 3 + 1 + 2) * 0.3) - 255)
Next i
Data = AlignBinaryData(GrayData)
Application.ScreenUpdating = True
bmp_to_csv = Data
End Function
'――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
Function AlignBinaryData(ByRef Data() As Long) As Long()
Dim i As Long
Dim j As Long
Dim cnt As Long
Dim out() As Long
ReDim out(UBound(Data))
cnt = 1
For i = 28 To 1 Step -1
For j = 27 To 0 Step -1
out(cnt) = Data((i * 28) - j)
cnt = cnt + 1
Next j
Next i
AlignBinaryData = out
End Function
以下では各関数で何を行っているかを解説していきます。
Function bmp_to_csv
関数「bmp_to_csv」は読み込まれたbmpファイルを数値化する関数です。
bmp画像をバイナリファイルとして読み取ることで、bmp画像の各ピクセルのRGB値を取得することができます。これを利用し、各ピクセルのグレースケールデータの値をすべて取得します。
(この手法については下記ページでまとめているので合わせて参照ください)
入力する画像はMNISTデータと同様の28×28(px)が前提なので、この関数により784個のグレースケール値の入った配列が出力されます。(この配列がニューラルネットワークの入力値となります)
ちなみにRGBをグレースケールに変換するには以下のような式を使います。
(コード内では数字を丸めていますが特に問題はありません)
K = R × 0.299 + G ×0.587 + B × 0.114
Function AlignBinaryData
関数「AlignBinaryData」は入力した配列の順番を反転することのできる関数です。
バイナリデータから単純に各ピクセルのグレースケール値を取得すると、上下が反転してしまっている状態です。(詳しくは「【バイナリデータ】VBAでBMP画像を読み込みExcel上でドット絵を作成する方法」参照)
しかし、ニューラルネットワークに推論させるには、学習させたMNISTデータと同じ形式でデータを入力する必要があります。要するに画像が上下反転しているとうまく推論ができないということです。
この関数ではその上下反転しているデータを正常な向きのデータに変換することができます。
まとめ
ここでは手書き文字データをニューラルネットワークに入力するために、画像を数値に変換するための関数を実装しました。
今回実装したcsv_Functionsモジュールの機能をまとめると以下の通りです。
Function bmp_to_csv:開いたbmpファイルを数値に変換する
Function AlignBinaryData:入力された配列の順番を反転する
ニューラルネットワークの実装と今回の関数さえ実装できれば、後は今回の関数によって出力される値をニューラルネットワークに入れるだけです。
参考書籍










