機械学習第9章
CNNによる画像認識
問題定義
CIFAR-10データセット
画素数32*32のカラーイメージデータが10種類のカテゴリーに分けられている
訓練用:5万枚
検証用:1万枚
カラー画像であるため(3,32,32)(色、縦、横)の3階テンソルで表現
奥行きに当たるインデックスのことをチャネルという
重要概念
畳み込み
3*3や5*5などの小さな正方形の配列を用意する
対応する要素間との積をとり、全ての要素を足し合わせる
入力チャネルは複数あり、関和演算は全チャネルにまたがって行われる
プーリング
max pooling
重なる領域を取らずにずらしていく
矩形領域のサイズは2*2が多い
画像を縮小する効果があるため、物体の大きさによらない普遍的な特徴量を抽出するのに向いている
PyTorchでのCNN実装
畳み込み関数:nn.Conv2d(関数の内部にパラメータを持つ)
プーリング関数:nn.MaxPool2d(関数の内部にパラメータを持たない)
一次化関数:nn.Flatten
共通関数の利用
パターンを抽出し、共通関数として定義する
損失計算
code:python
def eval_loss(loader, device, net, criterion):
# データローダから最初の1セットを取得する
for images, labels in loader:
break
# デバイスの割り当て
inputs = images.to(device)
labels = labels.to(device)
# 予測計算
outputs = net(inputs)
# 損失計算
loss = criterion(outputs, labels)
return loss
学習
今まで繰り返し計算していた箇所を関数呼び出しでまとめて行う
呼び出しの引数8つ
net : 学習対象のモデルインスタンス
optimizer : 最適化関数のインスタンス
criterion : 損失関数のインスタンス
num_epochs : 繰り返し数
train_loader : 訓練用データローダー
test_loader : 検証用のデータローダー
device : GPU or CPU
history : これまでのhistory
fit関数 追加学習用の実装部分
code:python
def fit(net, optimizer, criterion, num_epochs, train_loader, test_loader, device, history):
base_epochs = len(history)
for epoch in range(base_epochs, num_epochs+base_epochs):
train_loss = 0
train_acc = 0
# 訓練フェーズ
net.train()
count = 0
for inputs, labels in tqdm(train_loader):
count += len(lables)
inputs = inputs.to(device)
labels = labels.to(device)
# 予測フェーズ
net.eval()
count = 0
for inputs, labels in test_loader:
count += len(labels)
inputs = inputs.to(device)
labels = labels.to(device)
# 勾配の初期化
optimizer.zero_grad()
# 予測計算
outputs = net(inputs)
# 損失計算
loss = criterion(outputs, labels)
train_loss += loss.item()
# 勾配計算
loss.backward()
# パラメータ修正
optimizer.step()
# 予測値算出
predicted = torch.max(outputs, 1)1
# 正解件数算出
train_acc += (predicted == labels).sum().item()
# 損失と精度の計算
avg_train_loss = train_loss / count
avg_train_acc = train_acc / count
#予測フェーズ
net.eval()
count = 0
for inputs, labels in test_loader:
count += len(labels)
inputs = inputs.to(device)
labels = labels.to(device)
# 予測計算
outputs = net(inputs)
# 損失計算
loss = criterion(outputs, labels)
val_loss += loss.item()
# 予測値算出
predicted = torch.max(outputs, 1)1
# 正解件数算出
val_acc += (predicted == labels).sum().item()
# 損失と精度の計算
avg_val_loss = val_loss / count
avg_val_acc = val_acc / count
print (f'Epoch {(epoch+1)}/{num_epochs+base_epochs}, loss: {avg_train_loss:.5f} acc: {avg_train_acc:.5f} val_loss: {avg_val_loss:.5f}, val_acc: {avg_val_acc:.5f}')
item = np.array(epoch+1, avg_train_loss, avg_train_acc, avg_val_loss, avg_val_acc)
history = np.vstack((history, item))
return history
戻り値は2次元配列をnumpy形式で返す
実装
1データ準備
transforms定義
code:python
# transform1 1階テンソル化
transform1 = transform.Compose([
transforms.ToTensor(),
transforms.Normalize(0.5, 0.5),
transforms.Lambda(lambda x: x.view(-1)),
])
# transform2 正規化のみ実施
# 検証データのみ
transform2 = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(0.5, 0,5),
])
transform1が全結合型ニューラルネットワーク用
transform2がCNN用
データセット定義
code:python
data_root = './data'
# 訓練データセット1階テンソル版
train_set1 = datasets.CIFAR10(
root = data_root, train = True, download = True, transform = transform1)
# 検証用データセット1階テンソル版
test_set1 = datasets.CIFAR10(
root = root, train = False, dawnload = True, transform = transform1)
# 訓練データセット3階テンソル版
train_set1 = datasets.CIFAR10(
root = data_root, train = True, download = True, transform = transform2)
# 検証用データセット3階テンソル版
test_set1 = datasets.CIFAR10(
root = root, train = False, dawnload = True, transform = transform2)
データローダー定義
code:python
# ミニバッチサイズ指定
batch_size = 100
# 訓練用データローダー(シャッフルする)
train_loader1 = DataLoader(train_set1, batch_size=batch_size, shuffle=True)
# 検証用データローダ(シャッフルなし)
test_loader1 = DataLoader(test_set1, batch_size=batch_size, shuffle=True)
# 訓練用データローダー(シャッフルする)
train_loader2 = DataLoader(train_set2, batch_size=batch_size, shuffle=True)
# 検証用データローダ(シャッフルなし)
test_loader2 = DataLoader(test_set2, batch_size=batch_size, shuffle=True)
モデル定義(全結合版)
code省略 
検証データ精度は約53%
モデル定義(CNN版)
各ノードの次元数設定
code:python
# 入力次元数 今回は3*32*32=3072
n_input = image.view(-1).shape0
# 出力次元数 分類先クラス 今回は10
n_output = len(set(list(labels.data.numpy())))
# 隠れ層のノード数
n_hidden = 128
モデル定義
code:python
class CNN(nn.Module):
def __init__(self, n_output, n_hidden):
super().__init__()
self.conv1 = nn.Conv2d(3, 32, 3)
self.conv2 = nn.Conv2d(32, 32, 3)
self.relu = nn.ReLu(inplace=True)
self.maxpool = nn.MaxPool2d((2,2))
self.flatten = nn.Flatten()
self.l1 = nn.Linear(6272, n_hidden)
self.l2 = nn.Linear(n_hidden, n_output)
self.features = nn.Sequential(
self.conv1,
self.relu,
self.conv2,
self.relu,
self.maxpool)
self.classifire = nn.Sequential(
self.l1,
self.relu,
self.l2)
def forward(self, x):
x1 = self.features(x)
x2 = self.flatten(x1)
x3 = self.classifier(x2)
return x3
結果
モデル初期化と学習
code:python
# 乱数初期化
torch_seed()
# モデルインスタンス生成
net = CNN(n_output, n_hidden).to(device)
# 損失計算
criterion = nn.CrossEntropyLoss()
# 学習率
lr = 0.01
# 最適化関数:勾配降下法
optimizer = optim.SGD(net.parameters(), lr=lr)
# 繰り返し回数
num_epochs = 50
# 評価結果記録用
history2 = np.zeros((0,5))
#学習
history2 = fit(net, optimizer, criterion, num_epochs, train_loader2, test_loader2, device, history2)
評価
code:python
evaluate_history(history2)
精度60%
次章、チューニング技法を用いてさらに精度を高める
機械学習1章・2章
機械学習3章
機械学習第6章
機械学習第7章
機械学習第8章
機械学習第10章
機械学習第11章