Pytorchで画像分類の精度を高める
今回、画像分類で精度を高めるために複数データの入力できる学習モデルを作成した。その経緯から始めて実際のモデリングまでを書くことにする。 前提 今回は洋服の図面を読み込み、それがなんの種類かを判別するCNNを作成した。 図 […]
Filter by Category
今回、画像分類で精度を高めるために複数データの入力できる学習モデルを作成した。その経緯から始めて実際のモデリングまでを書くことにする。 前提 今回は洋服の図面を読み込み、それがなんの種類かを判別するCNNを作成した。 図 […]
pythonのOpenCVで輪郭を上手く抽出することができなかったが、いくつかの改善点により上手く行った経緯をここに書き残しておく。 改善前 これは50×50のスカートの画像である。単にfindcontourし […]
Jupyter NotebookでもBlackでコードフォーマット コードの可読性を上げて保守性を高めたり、コードの属人化を防いで生産性を向上させるためのルール(コーディング規約)に則った開発を行うために、ファントムでは […]
PythonのRequestsを使ってSlackに通知 フォームから送られた内容やプログラムの処理結果や途中結果をSlackに通知する方法です。 以下のコードのBOT USER TOKENとCHANNEL NAMEを任意 […]
2022年度 採用についてのお知らせ 概要2022年度の採用募集を開始します。(フルタイム、副業問わずビデオ会議等で意見交換からでもOKです。) 募集職種・インフラエンジニア・ウェブアプリケーションエンジニア・機械学習エ […]
Pythonのf文字列を使った書式パターン この記事で紹介したf文字列を使った文字列の操作ですが、文字列に変数を埋め込む際に書式を指定できます。0埋めして文字数を揃えたり、カンマで桁を区切ることも可能です。 カンマで桁区 […]
Pythonのf文字列を使った文字列の操作 Pythonのf文字列は{1}や{a}のように変数を{}(波括弧)で囲うことで、文字列の中に変数を挿入できるので直感的な記述ができるようになります。従来のように複数の変数や文字 […]
Pythonのargparseでコマンドライン引数をパース argparseモジュールを使って、Pythonを実行する際にコマンドライン引数を指定してプログラム内に情報を渡す方法です。 引数によって処理を変えたり、別々の […]
Announcement about Internships for 2022 日本語のページ OverviewWe’re now accepting applications for full remote […]
2022年度 インターンシップについてのお知らせ For English page 概要2022年度のインターンシップの募集を開始します。 募集職種・インフラエンジニア・ウェブアプリケーションエンジニア・機械学習エンジニ […]
最新情報をお届けするメルマガ始めます 本ブログも開始から3年ほどが経過しこれまでに多くの方にアクセスしていただきました。なかにはブログ経由でスタッフや学生インターンとして採用にいたったり、新規プロジェクト、新規案件をまか […]
ERROR: ResolutionImpossible docker-composeコマンドでビルドした際にERROR: ResolutionImpossibleというエラーが発生しました。このエラーは複数の原因があるよ […]
PyCharm&DockerでもBlackでコードフォーマット venvなどで環境構築されたプロジェクトであれば、PyCharmのFile Wacherというプラグインでファイルの保存時にBlackによるコードの […]
Pythonでソートが効かないリストを文字列を操作してソートさせる [‘01234_B.jpg?X=n…’,‘12340_A.jpg?X=n…’,& […]
PythonでXserverからメール送信 レンタルサーバーで処理が終わった時や進捗を確認したいときにPythonでメールを送る方法です。今回はXserverでPythonを実行していますが、他のレンタルサーバーでもホス […]
UnicodeEncodeError: ‘ascii’ codec can’t encode Pythonのprint() 関数で文字列を出力する時に以下の様なUnicodeEncod […]
2021年に最も読まれた記事ランキング 早いもので今年も残すところあとわずかとなりました。今年のまとめとして2021年に最も読まれたブログをランキング形式で発表します。 第5位 第4位 第3位 第2位 第1位 1位、2位 […]
dockerignoreで転送に時間がかかるファイルを除外 数GBを超えるSQLiteやメディアデータを含むプロジェクトをDocker Composeで起動する際に、ファイルの転送に時間がかかってしまいビルドがなかなか終 […]
Docker Composeで起動したコンテナ内に入る Docker Composeで起動したコンテナ内に入って処理やコマンドを実行する方法です。 コンテナ内に入るコマンド docker-compose up -dでコン […]
Failed to find Flask application or factory in module ‘NAME’. DockerでFlaskアプリケーションを起動する際にFailed to […]
今回、画像分類で精度を高めるために複数データの入力できる学習モデルを作成した。その経緯から始めて実際のモデリングまでを書くことにする。
今回は洋服の図面を読み込み、それがなんの種類かを判別するCNNを作成した。
図面ということで、基本的に白い背景に黒線が引かれただけの画像である。
次のサイトにもあるように、CNNはシルエットなどの情報に弱い性質がある。理由の1つはCNNの畳み込みが局所的なピクセルを見て判断するためである。写真など材質がわかるものであれば局所的に取りうる色の種類が無数にあり、特徴を見出すことが比較的容易であるのに対して、今回のような白い背景に黒い線だと局所的に取りうる色の種類が白と黒の組み合わせしかないため、局所的性質で判定することは非常に難しい。
また、CNNは「全体としてこういう形である」という大域的な図形を見ているわけではないことも難易度が上がる要因になっている。
https://ai-scholar.tech/articles/others/cnn-shap-ai-110
まずは単純なCNNを実装してみる。
import torch
import torch.nn as nn
import torch.optim as optimizers
import torch.nn.functional as F
class CNN(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(3, 64,
kernel_size=(7, 7),
stride=(2, 2),
padding=3)
self.bn1 = nn.BatchNorm2d(64)
self.relu1 = nn.ReLU()
self.pool1 = nn.MaxPool2d(kernel_size=(3, 3),
stride=(2, 2),
padding=1)
self.conv2 = nn.Conv2d(64,128,
kernel_size=(7, 7),
stride=(2, 2),
padding=3)
self.bn2 = nn.BatchNorm2d(128)
self.relu2 = nn.ReLU()
self.pool2 = nn.MaxPool2d(kernel_size=(3, 3),
stride=(2, 2),
padding=1)
self.conv3 = nn.Conv2d(128,256,
kernel_size=(7, 7),
stride=(2, 2),
padding=3)
self.bn3 = nn.BatchNorm2d(256)
self.relu3 = nn.ReLU()
self.pool3 = nn.MaxPool2d(kernel_size=(3, 3),
stride=(2, 2),
padding=1)
self.relu4 = nn.ReLU()
self.fc = nn.Linear(256, 1000)
#self.block_model1 = Block(64,256)
def forward(self, x):
h = self.conv1(x)
h = self.bn1(h)
h = self.relu1(h)
h = self.pool1(h)
h = self.conv2(h)
h = self.bn2(h)
h = self.relu2(h)
h = self.pool2(h)
h = self.conv3(h)
h = self.bn3(h)
h = self.relu3(h)
h = self.pool3(h)
h = F.avg_pool2d(h, kernel_size=h.size()[2:]).view(-1, h.size(1))
h = self.fc(h)
return h
pytorchを利用すればこれだけでモデルは完成である。
これを回した結果、それほどいい成績が出なかった。
そこで目をつけたのが次の論文である。
https://db-event.jpn.org/deim2019/post/papers/19.pdf
この論文によると、画像を加工したものを同時に入力することで精度が上がるらしいことがわかる。
今回作成する画像認識はシャツかパンツかスカートか、等の大雑把な種類を判別すればよいので、輪郭だけ抽出した画像を用意することで細々とした装飾に惑わされずに判定できるのではないか、という思惑がある。
ではそれを実装してみよう。
class CNN_Model(nn.Module):
def __init__(self, output_dim):
super().__init__()
self.out = nn.Linear(2000, output_dim)
self.cnn_origin = CNN()
self.cnn_contour = CNN()
def forward(self, x_origin, x_contour):
h_origin = self.cnn_origin(x_origin)
h_contour = self.cnn_contour(x_contour)
h = torch.cat((h_origin, h_contour),1)
h = torch.relu(h)
h = self.out(h)
y = F.softmax(h, dim=1)
return y
これで複数入力するモデルは完成である。
まず見るべきはforwardの引数である。ここに引数を増やせば入力するデータを増やすことができる。
引数の1つ目をオリジナルの画像、2つ目を輪郭抽出した画像を入力するようにした。
それぞれをまずCNNのモデルに通して特徴量を抽出する。その結果出てきた1000個のパラメータを結合して最終的にoutput_dim個のパラメータに出力すれば完成である。
今回のように、pytorchのモデルはclassで分割して使い回すことができる。この時、classで分割されたパラメータ(今回のCNNの各パラメータ)は移譲先のclassのパラメータとして再帰的に設定されるので、細かい挙動を気にせずにモデルを作成できる。self.cnn_originとself.cnn_contourは別々のパラメータとして設定されており、共有されているということはない。
ここで、結合するときにbackwardがちゃんと機能するように結合前後の層を設定する必要があることに注意してほしい。
ここまでできれば、あとはDataLoaderで学習データを読み込む機能とmodel.trainで学習する部分を書けば完成である。
群馬県でPythonを使ったAIやソフトウェアを開発している株式会社ファントムが運営しています。
メーリングリストに登録するとファントムの最新情報をお届けします
お客様のメールアドレスを共有することはありません