横浜国立大学理工学部建築都市環境系学科卒
一級鉄筋技能士
私たちの目的はAIを利活用し業務を改善することですが、AIの勉強には高等数学の知識が必要になってきます。
画像分類の学習では、「テンソル」「正規分布(ガウス分布)」「標準化」「損失関数」「最適化関数」など非常に難しい単語が登場します。
AIの普及率が低いのはこれらの難解な数学の知識が邪魔しているのも一因かと思います。
この記事では、画像データ(CIFAR10)を用いながらDataset、Dataloaderの作成過程、特に「テンソル」「正規分布(ガウス分布)」「標準化」の言葉の意味について詳しく説明します。
目次
CIFAR10を利用したpytorchの学習手順
CIFAR10は、10種類の「物体カラー写真」(乗り物や動物など)の画像データセットであり、画像分類を目的とした機械学習の研究やチュートリアルとして使用されています。
画像分類の手順は以下の通りです。
1 2 3 4 5 |
1.データを準備してDataset、Dataloaderを作成 2.Modelの定義 3.損失関数と最適化関数の定義 4.学習 5.テスト |
ここでは、「1.データを準備してDataset、Dataloaderを作成」についてみていきましょう。
Dataset、Dataloaderの作成過程コード
コードは以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import torch import torchvision import torchvision.transforms as transforms # データの前処理 # chを1次元にしてTensor化 > 標準化 transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) # バッチサイズ: 小分けにする学習データサイズ batch_size = 4 # DatasetとDataloader Pytorchでデータを管理するもの ## 訓練用データ trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True, num_workers=2) ## テスト用データ testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=2) # CIFAR10の10種の分類 classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') |
画像分類について
そもそも画像をコンピューターで処理するということはどういうことなのか?
画像の仕組みから見ていきましょう。
写真は赤、緑、青の3つの行列の集まり
コンピューターに画像を読み込ませるには、写真というデータを数字に変換させる必要があります。
カラー写真(500*500ピクセルの場合)は赤色の500*500の行列、緑色の500*500の行列、青色の500*500の行列の3つの行列からできています。
一つ一つのピクセルは256段階(0=白~255=黒)の濃淡で表示され、コンピューターはこの数字で画像がどのような色になっているのか認識しています。
テンソル=ndarray
テンソルは行列を集めたものと考えられています。
テンソルはndarrayそのもので、ndarray形式で保存されています。
テンソルの演算において、pythonではNumpyというライブラリがあり、Numpyを使うことによって非常に効率よくコードを書くことができます。
GPUを使用する際はNumpyのndarray型ではなくPytorchのTensor型に変換する
テンソルだったり、tensorだったり非常にわかりにくいところですが、基本的にはNumpyもPytorchも同じものです。
NumpyもPytorchも画像(テンソル)を取り扱うライブラリですが、GPUを使用するときはPytorchのTensor型に変換する必要があると覚えておきましょう。
データの前処理
データの前処理の部分について詳しく見ていきます。
1 2 3 4 5 |
# データの前処理 # chを1次元にしてTensor化 > 標準化 transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) |
Pytorchでは画像データを(赤/緑/青の3色の次元, 高さ, 幅)で取り扱っており、transformオブジェクトでは以下の処理がされています。
1 2 3 4 |
1.numpy.ndarrayをTensor化 2.各RGBの0〜255の値を255で割って[0, 1] の値にする(正規化) 3.標準化の式を使い、[0, 1] の範囲の値を [-1, 1]にすることで平均が0、標準偏差が1になるように変換 (正規分布→標準化→標準正規分布の作成) |
transforms.ToTensor()でTensor型に変換
GPUを使うことを前提としているので、.ToTensor()でTensor型に変換しています。
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))で標準化
正規分布にしただけでは標準化は完了しません。
平均が0、標準偏差が1の標準正規分布に変換することで標準化が完了することに注意します。
サンプル画像を以下のコードで取得して正しくTensor型になっているのか確認してみましょう。
Tensor型になったのか確認
1 2 3 4 5 6 |
#サンプル画像の取得 import wget site_url = 'https://itoishoukai.com/od_course/sample.jpg' file_name = wget.download(site_url) print(file_name) |
1 2 3 4 |
#取得した画像をtransformする import cv2 img = cv2.imread("sample.jpg") img_trans = transform(img) |
1 2 3 |
#確認 print(type(img_trans)) print(img_trans.shape) |
標準化ができたか確認
標準化が正しくできているかどうか以下のコードで確認します。
1 2 3 4 5 |
print("元の数値 = ", img[300,300,0]) print("(元の数値/255-平均0.5) / 標準偏差0.5 = ", (img[300,300,0]/255 - 0.5)/ 0.5) print("transformした後の数値 = ", img_trans[0, 300, 300]) print("最小", torch.min(img_trans)) print("最大", torch.max(img_trans)) |
よくあるエラー
実際に自分で動かしてみて発生したエラーの対処法を紹介します。
RuntimeError: The size of tensor a (3) must match the size of tensor b (4) at non-singleton dimension 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import cv2 img = cv2.imread("sample.jpg") img_trans = transform(img) import torch import torchvision import torchvision.transforms as transforms transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5,0.5,0.5,0.5),(0.5,0.5,0.5,0.5))]) batch_size = 4 trainset = torchvision.datasets.CIFAR10(root='./data',train=True,download=True,transform=transform) trainloader = torch.utils.data.DataLoader(trainset,batch_size=batch_size,shuffle=True,num_workers=2) testset = torchvision.datasets.CIFAR10(root='./data',train=True,download=True,transform=transform) testloader = torch.utils.data.DataLoader(trainset,batch_size=batch_size,shuffle=True,num_workers=2) classes = ('plane','cat','bird','cat','deer','dog','frog','horse','ship','truck') |
上記のように打ち間違えると、次のエラーが発生します。
1 |
RuntimeError: The size of tensor a (3) must match the size of tensor b (4) at non-singleton dimension 0 |
前述した標準化の部分のエラーです。
1 2 |
誤:transforms.Normalize((0.5,0.5,0.5,0.5),(0.5,0.5,0.5,0.5)) 正:transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) |
まとめ
Dataset、Dataloaderの作成過程では「テンソル」「正規分布(ガウス分布)」「標準化」などの難しい言葉が登場します。
全てを詳細に理解する必要はありませんが、知見として理解をしておくと便利です。