Contents
はじめに
今回も、Kaggleに公開されているデータセットを使っていきたいとおもいます。今回は、画像分類をkaggleのデータセットにあった図形のデータを使って行なっていきたいと思います。このデータセットには4つの図形の16,000の画像が含まれています。四角形、星形、円、三角形などがあります。このデータセット、MNISTの次に扱うのにいいのではないかと考え、今回はできる限りMNISTに近づけてあまり変更なく書けるようにしたいと思います。では、GoogleColaboratory上でskorchを使って画像分類をしていきたいと思います。
今回のデータセットのリンク
合わせて読みたい記事:
データセットの説明
図形の種類
四角形、星形、円、三角形
データセットの内訳
- 画像サイズ: 200×200
- 画像枚数:4000×4=16000枚
- グレイスケール画像
- ファイルのフォーマット: png
- 4クラス (四角形、星形、円、三角形)
ソースコード
表示→目次→ファイルをおすとGoogleColaboratory上のファイルを見ることができます。そしてアップロードの表示があると思うので、そこからファイルをアップロードできます。
データセット準備
まず、データセットを解凍していきます。
In[1]:
!unzip four-shapes.zip
In[2]:
!unzip shapes.zip
ディレクトリを扱いやすいように変えたいと思います。shapeというディレクトリを作り、その中に解凍してできたcircle、triangle、star、squareを放り込んでいきます。
In[3]:
!mkdir shape
In[4]:
!mv circle shape
!mv square shape
!mv triangle shape
!mv star shape
ライブラリの準備
PyTorch、skorchをインストールしておきます。
In[5]:
!pip install http://download.pytorch.org/whl/cu80/torch-0.4.1-cp36-cp36m-linux_x86_64.whl
!pip install torchvision
In[6]:
import torch
import numpy as np
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import torch.utils.data
import torch.backends.cudnn as cudnn
import torchvision
from torchvision import datasets, models, transforms
from sklearn.metrics import confusion_matrix, accuracy_score
import random
import os
import time
import skorch
from skorch import NeuralNetClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from PIL import Image
import matplotlib.pyplot as plt
% matplotlib inline
これをしないとGoogleColaboratory上でPIL周りでエラーを吐くのでやっておきます。
In[7]:
!pip install Pillow==4.0.0
!pip install PIL
!pip install image
import PIL
import image
データセットを変換
画像ディレクトリを指定し、Numpy配列のリストに変換します。今回、画像サイズは200×200でしたが、MNISTに近づけるため、28×28にリサイズしています。
In[8]:
from keras.preprocessing.image import load_img,img_to_array
img_size = (28,28)
dir_name = 'shape/'
labels = os.listdir(dir_name)
print(labels)
temp_img_array_list = []
temp_label_array_list = []
for label in labels:
img_list = dir_name + label+ '/'
imgs = os.listdir(img_list)
for img in imgs:
img_path = img_list + img
try:
img = PIL.Image.open(img_path)
img_resize = img.resize(img_size)
temp_img_array = img_to_array(img_resize) /255
temp_img_array_list.append(temp_img_array)
temp_label_array_list.append(label)
except:
print('not_jpg')
X_train = np.array(temp_img_array_list)
Y_train = np.array(temp_label_array_list)
次に、Y_trainの中身がstring型で怒られてしまうので変えておきます。
In[9]:
from sklearn import preprocessing
le = preprocessing.LabelEncoder()
le.fit(['star', 'circle', 'square', 'triangle'])
Y_train = le.transform(Y_train)
X_trainも同様にreshapeしておきます。
In[10]:
X_train = X_train.reshape(-1, 1, 28, 28)
print(X_train.shape)
Out[10]:
(14970, 1, 28, 28)
適当に出力させてみましょう。
In[11]:
import random
for i in range(3):
plt.imshow(random.choice(X_train).reshape(28, 28))
plt.show()
Out[11]:
あとは、学習用と検証用にデータセットを8:2の割合で分けます。
In[12]:
x_train, x_test, y_train, y_test = train_test_split(X_train, Y_train, test_size=0.2, stratify=Y_train)
これで準備はOKです。
ネットワーク構成
今回使ったネットワークはこちらになります。
In[13]:
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=5, stride=1, padding=2),
nn.ReLU(inplace=True),
nn.Conv2d(32, 32, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(32),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Dropout(p = 0.25),
nn.Conv2d(32, 64, kernel_size=3, stride=1,padding=1),
nn.BatchNorm2d(64),
nn.Conv2d(64, 64, kernel_size=3, stride=1, padding=1),
nn.BatchNorm2d(64),
nn.Conv2d(64, 128, kernel_size=3, stride=1,padding=1),
nn.Conv2d(128, 128, kernel_size=3, stride=1,padding=1),
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Dropout(p = 0.25),
)
self.classifier = nn.Sequential(
nn.Dropout(p = 0.25),
nn.Linear(128 * 7 * 7, 512),
nn.ReLU(inplace=True),
nn.Dropout(p = 0.25),
nn.Linear(512, 10),
)
def forward(self, x):
x = self.features(x)
x = x.view(x.size(0), -1)
x = self.classifier(x)
return x
gpu使えるようにしておきます。
In[14]:
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = Net().to(device)
model.to(device)
学習
skorchで学習させる書き方はsklearnライクに書けるので楽でいいですね。理想としてはデータセット作りとネットワークをPyTorchのように書くことなんですが、PyTorchのデータセットでうまく学習させられない…
In[15]:
net = NeuralNetClassifier(
model,
optimizer=torch.optim.Adam,
criterion=torch.nn.CrossEntropyLoss,
max_epochs=3,
lr=0.01,
iterator_train__batch_size=32,
iterator_train__shuffle=True,
device='cuda',
)
net.fit(x_train, y_train)
y_pred = net.predict(x_test)
print(classification_report(y_test, y_pred))
色分けを見てほしくて画像にしてみました。値がうまく更新できたら色付けされていることがわかりますね。
Out[15]:
クロスバリデーション
クロスバリデーションもさせていきます。注意ですが、ネットワークを初期化して試してください。そうしないといきなりパラメータがフィットすることになります。
In[16]:
from sklearn.model_selection import cross_val_predict
y_pred = cross_val_predict(net, x_train, y_train, cv=5)
Out[16]:
epoch train_loss valid_acc valid_loss dur
------- ------------ ----------- ------------ ------
1 1.3434 0.9025 0.2016 4.2686
2 0.1447 0.9943 0.0220 4.1791
3 0.0807 1.0000 0.0003 4.1682
epoch train_loss valid_acc valid_loss dur
------- ------------ ----------- ------------ ------
1 1.3261 0.5099 1.1078 4.1828
2 0.2648 0.9755 0.0548 4.1691
3 0.0663 0.7784 1.0881 4.1831
4 0.0629 0.9917 0.0291 4.1789
5 0.0475 0.5850 3.8713 4.2008
6 0.0347 0.9995 0.0009 4.2212
7 0.0270 0.9520 0.2029 4.1984
8 0.0373 0.9969 0.0281 4.2047
9 0.0420 0.9995 0.0027 4.1919
10 0.0100 0.9995 0.0043 4.2012
epoch train_loss valid_acc valid_loss dur
------- ------------ ----------- ------------ ------
1 1.3383 0.9447 0.2169 4.1576
2 0.1343 0.8884 0.4438 4.1873
3 0.1072 0.9964 0.0153 4.2117
4 0.0481 0.9745 0.1041 4.1953
5 0.0688 0.9948 0.0191 4.2305
6 0.0357 0.9984 0.0050 4.1959
7 0.0287 0.9995 0.0010 4.1960
8 0.0564 0.9896 0.0414 4.1984
9 0.0324 0.9990 0.0018 4.2019
10 0.0220 0.9995 0.0017 4.2069
epoch train_loss valid_acc valid_loss dur
------- ------------ ----------- ------------ ------
1 1.3012 0.6601 0.6910 4.1845
2 0.2643 0.9896 0.0403 4.1900
3 0.2043 0.7518 0.9719 4.1919
4 0.1427 0.9875 0.0600 4.1880
5 0.0916 0.9948 0.0533 4.2025
6 0.0571 0.9953 0.0396 4.2266
7 0.0462 0.9979 0.0122 4.2185
8 0.0506 0.9953 0.0130 4.2337
9 0.0330 0.7643 1.9964 4.2049
10 0.0609 0.9995 0.0014 4.1858
epoch train_loss valid_acc valid_loss dur
------- ------------ ----------- ------------ ------
1 1.1768 0.7138 0.8318 4.1600
2 0.1820 0.9473 0.1309 4.1634
3 0.0486 0.9984 0.0041 4.1864
4 0.0410 0.9802 0.0507 4.1888
5 0.0582 0.9990 0.0041 4.1932
6 0.0102 0.9995 0.0007 4.1938
7 0.0516 0.9943 0.0153 4.1946
8 0.0559 0.9995 0.0017 4.1843
9 0.0049 0.9995 0.0009 4.1889
10 0.0053 0.9995 0.0015 4.1871
モデル保存
今回学習してできたモデルを保存しておきましょう。
import pickle
filename = "shape_model.pkl"
with open(filename, "wb") as f:
pickle.dump(model, f)
ローカルにダウンロードしておきます。
from google.colab import files
files.download('shape_model.pkl')
いかがだったでしょうか。この図形のデータセットはすごく入門にぴったりだと思うのでぜひ使ってみてください。
最後まで読んでいただきありがとうございました。よろしければこの記事をシェアしていただけると励みになります。よろしくお願いします。