ディープラーニングで「ながら運転」を検知する(その3)

前回の記事では、データセットの中身を確認しました。

ディープラーニングで「ながら運転」を検知する(その1)

ディープラーニングで「ながら運転」を検知する(その2)

この記事では、ディープラーニングを使って「ながら運転」の分類分けをしていきたいと思います。

ラベルはC0からC9までありそれらを分類する問題です。

データセットはkaggleにあったものを使用します。

コードの流れは以下の通り。

  1. ファイル名の取得
  2. 画像の読み込み
  3. 前処理
  4. モデルの構築
  5. 機械学習、テスト

順番に見ていきたいと思いまーす。

ファイル名の取得

画像の枚数は2万2千枚ほどありましたが、全部使うとかなりメモリを使用するので、1カテゴリあたり400枚(全部で4000枚)を使うことにします。(なにせ私のPCはメモリ16GB)

Pythonのパッケージglobの便利なところは、枚数を指定して読み込めるところですね。

base_dir = "./train"
category = ["c0","c1","c2","c3","c4","c5","c6","c7","c8","c9"]
files=[]

for c in category:
    mypath =  base_dir + "/" + c + "/*.jpg"
    files.extend(glob.glob(mypath)[:400])

こんな感じでglobの後に[:400]と指定することで、各カテゴリ400枚だけピックしてリストに追記しています。

画像の読み込み

OpenCVで画像を読み込みますが、その際にBGRからRGBに変換し、画像サイズを縦・横それぞれ1/4にしています。

(最初1/2サイズでやっていたのですが、途中でメモリエラーが出たのでやめました。)

最後にnumpyの配列に変換してます。

カテゴリー名はラベルとしてyに追加していきます。

X = []
y = []
for i in files:
    img = cv2.imread(i)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = cv2.resize(img,(120,160))
    X.append(img)
    category = i.split("/")[2]
    y.append(category[1])
    
X = np.array(X)
y = np.array(y)

訓練画像とテスト画像に分割します。

from sklearn.model_selection import train_test_split
import keras

X_train, X_test,y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

4000枚のうち、訓練画像は80%、テスト画像は20%にすることにしました。

前処理

画像をintからfloatに変換します。

ちなみに、intからfloatに変換する際にメモリが十分足りておらずOOM(Out Of Memory)エラーが何度か発生しました。

その場合には、画像サイズを小さくするなり、枚数を減らすなりの工夫を行う必要があります。

ラベルはワンホットベクターに変換します。

num_classes = 10    
 
X_train = X_train.astype('float32') / 255
X_test = X_test.astype('float32') / 255
 
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

モデルの構築

畳み込みニューラルネットを組みます。

畳み込み4層からなるシンプルなネットワークです。

height = 120
witdh = 160
in_shape = (witdh,height,3)

model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same',
                 input_shape=in_shape))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
 
model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
 
model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes))
model.add(Activation('softmax'))

機械学習、テスト

学習を行ってその後に評価を行います。

model.compile(
    loss='categorical_crossentropy',
    optimizer='adam',
    metrics=['accuracy'])
 
hist = model.fit(X_train, y_train,
    batch_size=32, 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.98375 loss= 0.09991514410969103

98.37%!

そこそこ良い正解率が出ました。

事故を防止するために、車の中にカメラを積んでAIが監視するなんて未来が来るかもしれませんね。

人間がAIに監視されるなんて考えただけで嫌ですが。

おわり。