データマイニング(DM)- Python - CNN
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
「[[.NET 開発基盤部会 Wiki>http://dotnetdevelopmentinfras...
散布図
-[[戻る>ビジネス インテリジェンス(BI)]]
--[[CRISP-DM>データマイニング(DM)- CRISP-DM]]
--[[Excel>データマイニング(DM)- Excel]]
--[[KNIME>データマイニング(DM)- KNIME]]
--[[Python>データマイニング(DM)- Python]]
--[[Python - DL>データマイニング(DM)- Python - DL]]
---[[Python - DNN>データマイニング(DM)- Python - DNN]]
---Python - CNN
---[[Python - RNN>データマイニング(DM)- Python - RNN]]
--[[DataSet>データマイニング(DM)- DataSet]]
*目次 [#pf027881]
#contents
*概要 [#uf2c1f56]
[[CNN>ニューラルネットワーク#fb7864bd]]
*詳細 [#tc9899bd]
**主線 [#g51e65ba]
***手書き数字画像の認識 [#bbaf9696]
[[コチラ>ニューラルネットワーク(推論)#zf703d94]]の[[CNN...
-データセット
--ロード
from keras.datasets import mnist
(x_train_org, y_train_org), (x_test_org, y_test_org) = m...
print(x_train_org.shape, x_test_org.shape)
print(y_train_org.shape, y_test_org.shape)
--確認~
関数の定義は[[コチラ>#nb2b7282]]。
show_image_info(x_train_org, y_train_org, [0,1,2,3,4,5,6...
--変換
---XのKeras入力用型変換
x_train_std = x_train_org.astype('f')
x_test_std = x_test_org.astype('f')
---Xの画素を0.0-1.0の範囲に正規化
x_train_std /= 255
x_test_std /= 255
---正解ラベルの[[One-Hotエンコーディング>データマイニング...
Kerasでは正解ラベルはOne-Hotベクトル化が必要。~
・エンコーディング
y_train = np_utils.to_categorical(y_train_org, num_class...
y_test = np_utils.to_categorical(y_test_org, num_classes...
・デコーディング
print((y_train.argmax(axis=1) == y_train_org).all())
print((y_test.argmax(axis=1) == y_test_org).all())
-モデルの定義~
以下のように層を重ねて多層パーセプトロン(MLP)モデルを定義
--Flatten~
Flattenで画像行列をベクトル化
--Dense~
全結合層(Dense)に入力
--[[Activation(活性化関数)>ニューラルネットワーク#m1557...
活性化関数(線形、ReLU、tanh、Sigmoid関数)のモジュール
---線型の活性化関数:~
決定境界はパーセプトロンと変わらない。
---非線型の活性化関数:~
・決定境界が曲線となりよく分類できる。~
・ニューラルネットで大量のパラメータを用意することで複雑...
--Optimizers~
勾配降下法のアルゴリズムを決める。-> [[勾配降下法アルゴリ...
---SGD (MomentumSGD, NAG)
---Rmsprop
---Adam
---AdaDelta
---AdaGrad
--batchsize~
[[ミニバッチ学習>ニューラルネットワーク(学習)#h15bc15d]...
--epoch数~
学習の繰り返し回数を決める。
---計算リソースと相談
---基本は多い方が精度が高い
---過学習が起きることもある
--Activation(softmax関数)~
---予測を行うための計算処理([[順伝播計算>ニューラルネッ...
---softmax関数:出力層への入力を確率に変換する活性化関数
--誤差逆伝播法で学習を行うための計算処理([[逆伝播計算>ニ...
---cross_entropy誤差関数([[損失関数>ニューラルネットワー...
・cross_entropy誤差関数とはニューラルネットに特有の誤差関...
・softmax関数と対になるのはsoftmax_cross_entropy誤差関数~
・誤差逆伝播法を行ったときに手前の層まで更新が行き渡る。
---ニューラルネットは数式上では大規模な合成関数で、~
[[連鎖律(合成関数の微分の計算規則)>DS:数学的基礎 - 微...
---確率的勾配降下法:~
バッチ学習の最急降下法を改良しサンプリングを使って高速に...
# モデルのインスタンスを作成
model = Sequential()
# addメソッドで層を追加していく。
# Flatten:入力の変換層、入力サイズを指定
model.add(Flatten(input_shape=(28, 28)))
# 入力層
# Dense:全結合(線形結合)層、出力サイズを指定
model.add(Dense(900))
# Activation: 活性化関数を定義(ReLU
model.add(Activation('relu'))
# 多層化:繰り返し
model.add(Dense(1000))
model.add(Activation('relu'))
model.add(Dense(500))
model.add(Activation('relu'))
# 出力層:
# Dense:全結合(線形結合)層、出力サイズを指定
model.add(Dense(10))
# Activation: 活性化関数を定義(softmax
model.add(Activation('softmax'))
# 誤差関数、最適化手法、評価基準を指定してコンパイル
# ・損失関数 :categorical_crossentropy(分類の定番、回...
# ・最適化手法:SGD(基本的な確率的勾配降下法)
# ・評価方法 :Accuracy(精度)に指定
model.compile(loss='categorical_crossentropy',
optimizer=SGD(),
metrics=['accuracy'])
-モデルの学習~
以下のようなパラメタを設定して学習を実行する。
--訓練用入力データ、教師データ
--テスト用入力データ、教師データ
--[[batch_size:バッチサイズ、epochs:エポック数>ニューラ...
--varbose:学習時の表示~
・0:表示なし~
・1:通常表示~
・2:エポックと出力のみ表示
batch_size = 100
n_epoch = 20
# Keras Model の fit() は History オブジェクトを返す
hist = model.fit(x_train_std, y_train,
validation_data=(x_test_std, y_test),
batch_size=batch_size,
epochs=n_epoch,
verbose=1
)
※ batch_size、epochsについては[[コチラ>ニューラルネットワ...
-モデルの推論~
関数の定義は[[コチラ>#nb2b7282]]。
index = 10
show_image_info(x_test_org, y_test_org, [0,1,2,3,4,5,6,7...
predict = model.predict(x_test_std[index].reshape(1, 28,...
answer = y_test_org[index]
print('predict: ', predict)
print('answer : ', answer)
if predict == answer:
print('正解')
else:
print('不正解')
-モデルの評価
--テストデータで評価
model.evaluate(x_test_std, y_test) #(損失値、精度)を返す
--訓練データで評価~
エポック毎の精度(acc)と損失値(loss)
---val_~はテストデータ、~
それ以外は訓練データに対応する。
hist.history
---グラフへの表示~
・関数定義
# 損失値(Loss)の遷移のプロット
def plot_history_loss(hist):
plt.plot(hist.history['loss'],label="loss for traini...
plt.plot(hist.history['val_loss'],label="loss for va...
plt.title('model loss')
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(loc='best')
plt.show()
# 精度(Accuracy)の遷移のプロット
def plot_history_acc(hist):
plt.plot(hist.history['accuracy'],label="accuracy fo...
plt.plot(hist.history['val_accuracy'],label="accurac...
plt.title('model accuracy')
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.legend(loc='best')
plt.ylim([0, 1])
plt.show()
・グラフ表示
plot_history_loss(hist)
plot_history_acc(hist)
--混同行列を出力~
間違い易い、組合せが解る(1・7、2・7、3・8、3・9、4・9、7...
result = model.predict(x_test_std).argmax(axis=1)
confmat = cm(y_test_org, result) # y_testはOne-Hot表現前
confmat
--[[混同行列による指標の表示関数>データマイニング(DM)- ...
print_metrics(y_test_org, result) # y_testはOne-Hot表現前
--間違った画像の出力~
関数の定義は[[コチラ>#nb2b7282]]。
index = (y_test_org != result)
for i, val in enumerate(index):
if val == True:
print('predict: ', result[i])
print('answer : ', y_test_org[i])
show_image_info(x_test_org, y_test_org, [0,1,2,3...
***商品の自動タグ付け [#n1b78a93]
-[[データセット>データマイニング(DM)- DataSet#cad2f27a]]
--ロード
---サイトから取ってくる場合だが、
import os
from urllib import request
os.mkdir('./datasets')
url = 'https://.../train.pickle'
request.urlretrieve(url, './datasets/train.pickle')
url = 'https://.../test.pickle'
request.urlretrieve(url, './datasets/test.pickle')
url = 'https://.../label.pickle'
request.urlretrieve(url, './datasets/label.pickle')
---[[Kerasデータセット>データマイニング(DM)- DataSet#ca...
from keras.datasets import cifar10
(x_train,y_train),(x_test,y_test)=cifar10.load_data()
--確認
---関数を定義
def unpickle(file):
import pickle
with open(file, 'rb') as f:
return pickle.load(f, encoding='bytes')
---関数で読込
train = unpickle('./datasets/train.pickle')
test = unpickle('./datasets/test.pickle')
label = unpickle('./datasets/label.pickle')
---変数に代入
x_train_org = train['data']
y_train_org = train['label']
x_test_org = test['data']
y_test_org = test['label']
print(x_train_org.shape)
print(y_train_org.shape)
print(x_test_org.shape)
print(y_test_org.shape)
--変換
---[[要素の並び順を入れ替える>NumPy#ud48adc4]]~
(Opencv, Kerasの仕様の関係上
# サンプル数, height, width, channelへ変更
x_train = x_train_org.transpose([0, 2, 3, 1])
x_test = x_test_org.transpose([0, 2, 3, 1])
---XのKeras入力用型変換
x_train_std = x_train.astype('f')
x_test_std = x_test.astype('f')
---Xの画素を0.0-1.0の範囲に正規化
x_train_std /= 255
x_test_std /= 255
---正解ラベルの[[One-Hotエンコーディング>データマイニング...
Kerasでは正解ラベルはOne-Hotベクトル化が必要。~
・エンコーディング
y_train = np_utils.to_categorical(y_train_org, num_class...
y_test = np_utils.to_categorical(y_test_org, num_classes...
・デコーディング
print((y_train.argmax(axis=1) == y_train_org).all())
print((y_test.argmax(axis=1) == y_test_org).all())
---画像とラベルを確認~
関数の定義は[[コチラ>#nb2b7282]]。
show_image_info(x_train, y_train_org, label, 1300)
-モデルの定義~
畳み込み層とプーリング層が3層、全結合層が2層の[[CNNモデル...
--input_shape:入力の[[テンソル>NumPy#h768806a]]の形
--filters:カーネル数=フィルター数=特徴マップ数
--kernel_size:カーネルのサイズ(辺のピクセル数
--strides:カーネルをスライドさせる際のピクセル数
--padding:画像の縁取り処理における縁取り幅(kernel_size=...
model = Sequential()
# 畳み込み層とプーリング層1
model.add(Conv2D(input_shape=(32, 32, 3), filters=64, ke...
# バッチ正規化の追加位置
model.add(MaxPool2D(pool_size=(2, 2))) # プーリング増
model.add(Activation('relu'))
# 畳み込み層とプーリング層2
model.add(Conv2D(filters=128, kernel_size=(4, 4), stride...
# バッチ正規化の追加位置
model.add(MaxPool2D(pool_size=(2, 2))) # プーリング増
model.add(Activation('relu'))
# 畳み込み層とプーリング層3
model.add(Conv2D(filters=128, kernel_size=(4, 4), stride...
# バッチ正規化の追加位置
model.add(MaxPool2D(pool_size=(2, 2))) # プーリング増
model.add(Activation('relu'))
model.add(Flatten())
# 全結合層1
model.add(Dense(512))
model.add(Activation('relu'))
# Dropoutの追加位置
# 全結合層2
model.add(Dense(5))
model.add(Activation('softmax'))
# コンパイル
model.compile(loss='categorical_crossentropy',
optimizer=SGD(0.01), # 学習率:0.01
metrics=['accuracy'])
-モデルの学習
batch_size = 500
n_epoch = 30
hist = model.fit(x_train_std , y_train,
validation_data=(x_test_std, y_test),
batch_size=batch_size,
epochs=n_epoch,
verbose=1)
-モデルの推論~
関数の定義は[[コチラ>#nb2b7282]]。
index = 10
show_image_info(x_train, y_train_org, label, index)
predict = model.predict(x_test_std[index].reshape(1, 32,...
answer = y_test_org[index]
print('predict: ', predict)
print('answer : ', answer)
if predict == answer:
print('正解')
else:
print('不正解')
-モデルの評価
--テストデータで評価~
[[コチラ>#bbaf9696]]と同じ。
--訓練データで評価
---[[コチラ>#bbaf9696]]と同じ。
---訓練不足であることが解る。
--混同行列を出力~
[[コチラ>#bbaf9696]]と同じ。
--メトリック表示~
[[コチラ>#bbaf9696]]と同じ。
--間違った画像の出力~
[[コチラ>#bbaf9696]]とホボ同じ。
index = (y_test_org != result)
for i, val in enumerate(index):
if val == True:
print('predict: ', result[i])
print('answer : ', y_test_org[i])
show_image_info(x_test, y_test_org, label, i)
-性能向上
--訓練不足を補う~
batch_size, epochs=n_epoch
--チューニングを行う
---[[過学習の抑止>#yb34decb]]
---[[画像の前処理>#o122ce57]]
---[[勾配降下法アルゴリズムの選択>データマイニング(DM)-...
---[[転移学習、ファイン・チューニング>#se734ba8]]
-その他の[[CNNモデル>ニューラルネットワーク#fb7864bd]]~
ググると色々出てくる。計算量から[[GPU>深層学習(deep lear...
**共通項 [#x6c0f300]
***画像やラベルの確認 [#nb2b7282]
-画像の一覧で概要を捉える。
-画像とラベルを確認する。
def show_image_info(x, y, label, index):
print(label[y[index]])
plt.imshow(x[index].astype(np.uint8))
plt.show()
-一致、不一致を確認
***CNNにおける過学習の解決 [#yb34decb]
-[[DNN一般の過学習の解決>データマイニング(DM)- Python -...
--データ正規化
--重みの初期化
--早期終了(early stopping)~
--バッチ正規化(Batch Normalization)~
--ドロップアウト(Dropout)~
-CNN限定の過学習の解決
--前述の「DNN一般の過学習の解決」を参照
--データ正規化(画像)~
[[主線中の「Xの画素を0.0-1.0の範囲に正規化」を参照>#g51e6...
--[[データ拡張(data augmentation)>#o122ce57]]~
--[[バッチ正規化(Batch Normalization)>#n1b78a93]](モデ...
同一ニューロン(CNNではチャネル)でバッチデータに跨って平...
--バッチサイズに依存しない正規化手法~
バッチサイズが大き過ぎると正規化の効果が低下する可能性が...
---レイヤー正規化~
単一データで、複数ニューロン(CNNではチャネル)に跨って平...
---インスタンス正規化~
同一ニューロン(CNNではチャネル)や特徴マップについてのみ...
---グループ正規化~
ニューロン(CNNではチャネル)をn個にグルーピングしレイヤ...
***画像の前処理(様々な変換処理) [#o122ce57]
[[OpenCV]]を使用する。
-lenna.pngの
--ダウンロード
url = 'https://upload.wikimedia.org/wikipedia/en/7/7d/Le...
request.urlretrieve(url, 'lenna.png')
--読込・確認
img = cv2.imread('lenna.png')
print(type(img))
print(img.shape)
plt.imshow(img) # OpenCVはBGR解釈なので青みがかる。
--変換して保存
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # RGB解釈に変...
plt.imshow(img) # 元のRGB解釈の色合いで表示される。
cv2.imwrite('new_lenna.jpg', img) # RGB解釈で保存
-様々な変換処理
--比較関数を定義
def diff_image_info(img1, img2):
print(img1.shape)
print(img2.shape)
plt.subplot(1, 2, 1)
plt.imshow(img1)
plt.subplot(1, 2, 2)
plt.imshow(img2)
--リサイズ~
学習に画像データを入力するときは画像のサイズを揃える。
img2 = cv2.resize(img, (224, 224))
diff_image_info(img, img2)
--切り抜き~
画像の一部を切り抜く処理はarrayのスライシングで実装。
---ピクセル
img2 = img[100:400,100:400,:]
diff_image_info(img, img2)
---比率
h, w, c = img.shape
img2 = img[:, int(w * (1/5)): int(w *(4/5)), :]
diff_image_info(img, img2)
--明るさ調整
---グレースケール化~
色の意味合いが低い場合、モノクロ画像に変換し計算量を減ら...
grayed = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
diff_image_info(img, grayed)
---2値化~
グレーを使わない白と黒の2色に変換。~
スクリーン・トーンと同様の表現で、更に計算量を減らす。~
th, binary = cv2.threshold(grayed, 125, 255, cv2.THRESH_...
diff_image_info(grayed, binary)
---平滑化~
画像をぼやかしノイズ(ガサつきなど)を取り除く。
blurred = cv2.GaussianBlur(binary, (11, 11), 0)
diff_image_info(binary, blurred)
---ヒストグラム平坦化~
画素値のヒストグラムが全体的に平になるように濃度変換する...
画像の明るさの範囲を引き伸ばすと明暗部分でも輪郭線が認識...
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
clahed = clahe.apply(grayed)
diff_image_info(grayed, clahed)
---Mean Subtraction~
0~1正規化と合わせた標準化のようなスケーリング処理~
BatchNormalizationのように共変量シフトを抑制できる。
img2 = x.astype('f')
img2 /= 255 # 0~1正規化
img2 -= np.mean(img2) # スケーリング
diff_image_info(img, img2)
※ img単位ではなくxに対して適用できる。
---画像のピクセル値の正規化
img2 = img.astype('f')
img2 -= img.min()# 最小値を引く
img2 /= img.max()# 最大値で割る
diff_image_info(img, img2)
※ img単位ではなくxに対して適用できる。
--[[データ拡張(data augmentation)>ニューラルネットワー...
---左右反転
flipped = cv2.flip(img, 1)
diff_image_info(img, flipped)
---回転~
・関数定義
def opencv_rotate(img, angle=30):
size = (img.shape[0], img.shape[1])
center = (int(size[0]/2), int(size[1]/2))
rotation_matrix = cv2.getRotationMatrix2D(center, an...
return cv2.warpAffine(img, rotation_matrix, size)
・回転実行
rotated = opencv_rotate(img, 30)
diff_image_info(img, rotated)
---並進~
・関数定義
def opencv_move(img, h=100, v=50):
rows, cols, channnels = img.shape
M = np.float32([[1,0,h],[0,1,v]])
return cv2.warpAffine(img, M, (cols, rows))
・並進実行
moved = opencv_move(img, 200, 100)
diff_image_info(img, moved)
---拡大(クロップ)~
画像サイズを変えずにズームする
・関数定義
def opencv_zoomin(img, h=2.0, v=2.0):
zoomed = cv2.resize(img, None, fx=h, fy=v)
height_1, width_1, channel_1 = img.shape
height_2, width_2, channel_2 = zoomed.shape
x = int((width_2 - width_1) / 2)
y = int((height_2 - height_1) / 2)
return zoomed[y:y+height_1, x:x+width_1]
・拡大実行
zoomed = opencv_zoomin(img, 2, 3)
diff_image_info(img, zoomed)
---ガンマ変換~
画像の明るさを全体的に明るく or 暗くする処理~
・関数定義
def opencv_gamma(img, gamma=0.5):
look_up_table = np.zeros((256, 1), dtype='uint8')
for i in range(256):
look_up_table[i][0] = 255 * pow(float(i) / 255, ...
return cv2.LUT(img, look_up_table)
・ガンマ変換
img_gamma = opencv_gamma(img, 0.3)
diff_image_info(img, img_gamma)
---ガウシアンノイズ~
画像の加工過程で発生する粒が散らばったようなノイズを加え...
・関数定義
def opencv_gaussian(img, loc=0.0, scale=5.0):
row, col, ch = img.shape
noise = np.random.normal(loc,scale,(row,col,ch))
noise = noise.reshape(row,col,ch)
noised = img + noise
noised /= 255
return noised
・ガウシアンノイズ
img_gaussian = opencv_gaussian(img, 50, 100)
diff_image_info(img, img_gaussian)
---色の三属性の調整~
・コントラスト(色相:hue)~
・ブライトネス(輝度:brightness)~
・カラフルネス(彩度:saturation)
-関数例~
get_changedとget_augmentedは別々に定義する。~
get_augmentedはtrainに対してのみ実行してtestに対しては実...
--バッチ変換
def get_changed(img):
# グレースケール化
...
# ヒストグラム平坦化
...
# 平滑化
...
# カラーでなくなっている場合、
# 次元が減っているので、追加する。
return blurred[:,:,np.newaxis]
--バッチ拡張
def get_augmented(img):
# 左右反転
if np.random.rand() > 0.5:
img = cv2.flip(img, 1)
# 左右度回転
if np.random.rand() > 0.5:
size = (img.shape[0], img.shape[1])
center = (int(size[0]/2), int(size[1]/2))
angle = np.random.randint(-45, 45) # -45 ~ +45 ...
rotation_matrix = cv2.getRotationMatrix2D(center...
img = cv2.warpAffine(img, rotation_matrix, size)
return img
plt.imshow(get_augmented(x_train[1300]).astype(np.uint8))
***[[転移学習>深層学習のテクニック#ebe9edcc]]、[[ファイン...
-全結合層部分を含まない学習済みモデルの読込
--weights :重みの初期値('random': ランダム, 'imagen...
--include_top :全結合層のダウンロード(True: する, False...
--input_tensor:入力[[テンソル>NumPy#h768806a]]の型(縦, ...
base_model = VGG16(weights='imagenet', include_top=False...
# inputs.output_shape => (None, 1, 1, 512)
-追加する全結合層部分を定義
n_class = 5
top_model = Sequential()
top_model.add(Flatten(input_shape=inputs.output_shape[1:...
top_model.add(Dense(256))
top_model.add(Activation('relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(n_class))
top_model.add(Activation('softmax'))
-全結合層部分を含まない学習済みモデルに全結合層部分を追加
model = Model(inputs=base_model.input, outputs=top_model...
-転移学習は既存部分を再学習しない、ファイン・チューニング...
--既存部分の畳み込み層のパラメタを再学習しないように固定...
# for layer in model.layers[:-last_few_layers]: # 先頭~...
# スライシングでモデルの15層目までのパラメタを固定
for layer in model.layers[:15]:
layer.trainable = False
--学習率を通常の 10^-2 倍程度に小さくする。
model.compile(loss='categorical_crossentropy',
optimizer=SGD(lr=0.0001),
metrics=['accuracy'])
-モデルの確認と試用
--確認
model.summary()
--前処理
---関数定義
def preprocess_vgg16(img):
# リサイズ
img= cv2.resize(img, (32, 32))
# RGBからそれぞれvgg指定の値を引く
# (mean-subtractionに相当)
img[:, :, 0] -= 103.939
img[:, :, 1] -= 116.779
img[:, :, 2] -= 123.68
return img
---前処理実行~
leakageの防止(データ分割後にデータ変換・拡張等)~
なお、get_augmented、get_changedについては[[画像の前処理>...
x_train_list = []
for img in x_train:
x_train_list.append(preprocess_vgg16(get_augmented(g...
x_train_aug = np.array(x_train_list)
x_test_list = []
for img in x_test:
x_test_list.append(preprocess_vgg16(get_augmented(ge...
x_test_aug = np.array(x_test_list)
--試用~
調整てfitを行う([[前述の手順>#n1b78a93]])。
batch_size = 100
n_epoch = 1 # 試用なので回数を減らす
-以下は、tensorflow_hubで学習済みResNetの転移学習の例。
import tensorflow as tf
import tensorflow_hub as hub
IMAGE_SIZE = (224, 224)
out_features = 10
model_handle = "https://tfhub.dev/google/bit/s-r50x3/1"
do_fine_tuning = False
do_dense_train = True
model = tf.keras.Sequential([
tf.keras.layers.InputLayer(input_shape=IMAGE_SIZE + (3...
hub.Keras.Layer(model_handle, trainable=do_fine_tuning),
tf.keras.layers.Dense(out_features, trainable=do_dense...
])
model.summary()
*参考 [#j26b50a4]
-作成中のコンテンツへのリンク - OSSコンソーシアム~
https://www.osscons.jp/joho108j0-537
**[[scikit-learn]] [#ucea6e4b]
**[[TensorFlow・Keras]] [#k4e2cb7b]
**[[畳み込みニューラルネットワーク(CNN)]] [#h89f95c3]
終了行:
「[[.NET 開発基盤部会 Wiki>http://dotnetdevelopmentinfras...
散布図
-[[戻る>ビジネス インテリジェンス(BI)]]
--[[CRISP-DM>データマイニング(DM)- CRISP-DM]]
--[[Excel>データマイニング(DM)- Excel]]
--[[KNIME>データマイニング(DM)- KNIME]]
--[[Python>データマイニング(DM)- Python]]
--[[Python - DL>データマイニング(DM)- Python - DL]]
---[[Python - DNN>データマイニング(DM)- Python - DNN]]
---Python - CNN
---[[Python - RNN>データマイニング(DM)- Python - RNN]]
--[[DataSet>データマイニング(DM)- DataSet]]
*目次 [#pf027881]
#contents
*概要 [#uf2c1f56]
[[CNN>ニューラルネットワーク#fb7864bd]]
*詳細 [#tc9899bd]
**主線 [#g51e65ba]
***手書き数字画像の認識 [#bbaf9696]
[[コチラ>ニューラルネットワーク(推論)#zf703d94]]の[[CNN...
-データセット
--ロード
from keras.datasets import mnist
(x_train_org, y_train_org), (x_test_org, y_test_org) = m...
print(x_train_org.shape, x_test_org.shape)
print(y_train_org.shape, y_test_org.shape)
--確認~
関数の定義は[[コチラ>#nb2b7282]]。
show_image_info(x_train_org, y_train_org, [0,1,2,3,4,5,6...
--変換
---XのKeras入力用型変換
x_train_std = x_train_org.astype('f')
x_test_std = x_test_org.astype('f')
---Xの画素を0.0-1.0の範囲に正規化
x_train_std /= 255
x_test_std /= 255
---正解ラベルの[[One-Hotエンコーディング>データマイニング...
Kerasでは正解ラベルはOne-Hotベクトル化が必要。~
・エンコーディング
y_train = np_utils.to_categorical(y_train_org, num_class...
y_test = np_utils.to_categorical(y_test_org, num_classes...
・デコーディング
print((y_train.argmax(axis=1) == y_train_org).all())
print((y_test.argmax(axis=1) == y_test_org).all())
-モデルの定義~
以下のように層を重ねて多層パーセプトロン(MLP)モデルを定義
--Flatten~
Flattenで画像行列をベクトル化
--Dense~
全結合層(Dense)に入力
--[[Activation(活性化関数)>ニューラルネットワーク#m1557...
活性化関数(線形、ReLU、tanh、Sigmoid関数)のモジュール
---線型の活性化関数:~
決定境界はパーセプトロンと変わらない。
---非線型の活性化関数:~
・決定境界が曲線となりよく分類できる。~
・ニューラルネットで大量のパラメータを用意することで複雑...
--Optimizers~
勾配降下法のアルゴリズムを決める。-> [[勾配降下法アルゴリ...
---SGD (MomentumSGD, NAG)
---Rmsprop
---Adam
---AdaDelta
---AdaGrad
--batchsize~
[[ミニバッチ学習>ニューラルネットワーク(学習)#h15bc15d]...
--epoch数~
学習の繰り返し回数を決める。
---計算リソースと相談
---基本は多い方が精度が高い
---過学習が起きることもある
--Activation(softmax関数)~
---予測を行うための計算処理([[順伝播計算>ニューラルネッ...
---softmax関数:出力層への入力を確率に変換する活性化関数
--誤差逆伝播法で学習を行うための計算処理([[逆伝播計算>ニ...
---cross_entropy誤差関数([[損失関数>ニューラルネットワー...
・cross_entropy誤差関数とはニューラルネットに特有の誤差関...
・softmax関数と対になるのはsoftmax_cross_entropy誤差関数~
・誤差逆伝播法を行ったときに手前の層まで更新が行き渡る。
---ニューラルネットは数式上では大規模な合成関数で、~
[[連鎖律(合成関数の微分の計算規則)>DS:数学的基礎 - 微...
---確率的勾配降下法:~
バッチ学習の最急降下法を改良しサンプリングを使って高速に...
# モデルのインスタンスを作成
model = Sequential()
# addメソッドで層を追加していく。
# Flatten:入力の変換層、入力サイズを指定
model.add(Flatten(input_shape=(28, 28)))
# 入力層
# Dense:全結合(線形結合)層、出力サイズを指定
model.add(Dense(900))
# Activation: 活性化関数を定義(ReLU
model.add(Activation('relu'))
# 多層化:繰り返し
model.add(Dense(1000))
model.add(Activation('relu'))
model.add(Dense(500))
model.add(Activation('relu'))
# 出力層:
# Dense:全結合(線形結合)層、出力サイズを指定
model.add(Dense(10))
# Activation: 活性化関数を定義(softmax
model.add(Activation('softmax'))
# 誤差関数、最適化手法、評価基準を指定してコンパイル
# ・損失関数 :categorical_crossentropy(分類の定番、回...
# ・最適化手法:SGD(基本的な確率的勾配降下法)
# ・評価方法 :Accuracy(精度)に指定
model.compile(loss='categorical_crossentropy',
optimizer=SGD(),
metrics=['accuracy'])
-モデルの学習~
以下のようなパラメタを設定して学習を実行する。
--訓練用入力データ、教師データ
--テスト用入力データ、教師データ
--[[batch_size:バッチサイズ、epochs:エポック数>ニューラ...
--varbose:学習時の表示~
・0:表示なし~
・1:通常表示~
・2:エポックと出力のみ表示
batch_size = 100
n_epoch = 20
# Keras Model の fit() は History オブジェクトを返す
hist = model.fit(x_train_std, y_train,
validation_data=(x_test_std, y_test),
batch_size=batch_size,
epochs=n_epoch,
verbose=1
)
※ batch_size、epochsについては[[コチラ>ニューラルネットワ...
-モデルの推論~
関数の定義は[[コチラ>#nb2b7282]]。
index = 10
show_image_info(x_test_org, y_test_org, [0,1,2,3,4,5,6,7...
predict = model.predict(x_test_std[index].reshape(1, 28,...
answer = y_test_org[index]
print('predict: ', predict)
print('answer : ', answer)
if predict == answer:
print('正解')
else:
print('不正解')
-モデルの評価
--テストデータで評価
model.evaluate(x_test_std, y_test) #(損失値、精度)を返す
--訓練データで評価~
エポック毎の精度(acc)と損失値(loss)
---val_~はテストデータ、~
それ以外は訓練データに対応する。
hist.history
---グラフへの表示~
・関数定義
# 損失値(Loss)の遷移のプロット
def plot_history_loss(hist):
plt.plot(hist.history['loss'],label="loss for traini...
plt.plot(hist.history['val_loss'],label="loss for va...
plt.title('model loss')
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(loc='best')
plt.show()
# 精度(Accuracy)の遷移のプロット
def plot_history_acc(hist):
plt.plot(hist.history['accuracy'],label="accuracy fo...
plt.plot(hist.history['val_accuracy'],label="accurac...
plt.title('model accuracy')
plt.xlabel('epoch')
plt.ylabel('accuracy')
plt.legend(loc='best')
plt.ylim([0, 1])
plt.show()
・グラフ表示
plot_history_loss(hist)
plot_history_acc(hist)
--混同行列を出力~
間違い易い、組合せが解る(1・7、2・7、3・8、3・9、4・9、7...
result = model.predict(x_test_std).argmax(axis=1)
confmat = cm(y_test_org, result) # y_testはOne-Hot表現前
confmat
--[[混同行列による指標の表示関数>データマイニング(DM)- ...
print_metrics(y_test_org, result) # y_testはOne-Hot表現前
--間違った画像の出力~
関数の定義は[[コチラ>#nb2b7282]]。
index = (y_test_org != result)
for i, val in enumerate(index):
if val == True:
print('predict: ', result[i])
print('answer : ', y_test_org[i])
show_image_info(x_test_org, y_test_org, [0,1,2,3...
***商品の自動タグ付け [#n1b78a93]
-[[データセット>データマイニング(DM)- DataSet#cad2f27a]]
--ロード
---サイトから取ってくる場合だが、
import os
from urllib import request
os.mkdir('./datasets')
url = 'https://.../train.pickle'
request.urlretrieve(url, './datasets/train.pickle')
url = 'https://.../test.pickle'
request.urlretrieve(url, './datasets/test.pickle')
url = 'https://.../label.pickle'
request.urlretrieve(url, './datasets/label.pickle')
---[[Kerasデータセット>データマイニング(DM)- DataSet#ca...
from keras.datasets import cifar10
(x_train,y_train),(x_test,y_test)=cifar10.load_data()
--確認
---関数を定義
def unpickle(file):
import pickle
with open(file, 'rb') as f:
return pickle.load(f, encoding='bytes')
---関数で読込
train = unpickle('./datasets/train.pickle')
test = unpickle('./datasets/test.pickle')
label = unpickle('./datasets/label.pickle')
---変数に代入
x_train_org = train['data']
y_train_org = train['label']
x_test_org = test['data']
y_test_org = test['label']
print(x_train_org.shape)
print(y_train_org.shape)
print(x_test_org.shape)
print(y_test_org.shape)
--変換
---[[要素の並び順を入れ替える>NumPy#ud48adc4]]~
(Opencv, Kerasの仕様の関係上
# サンプル数, height, width, channelへ変更
x_train = x_train_org.transpose([0, 2, 3, 1])
x_test = x_test_org.transpose([0, 2, 3, 1])
---XのKeras入力用型変換
x_train_std = x_train.astype('f')
x_test_std = x_test.astype('f')
---Xの画素を0.0-1.0の範囲に正規化
x_train_std /= 255
x_test_std /= 255
---正解ラベルの[[One-Hotエンコーディング>データマイニング...
Kerasでは正解ラベルはOne-Hotベクトル化が必要。~
・エンコーディング
y_train = np_utils.to_categorical(y_train_org, num_class...
y_test = np_utils.to_categorical(y_test_org, num_classes...
・デコーディング
print((y_train.argmax(axis=1) == y_train_org).all())
print((y_test.argmax(axis=1) == y_test_org).all())
---画像とラベルを確認~
関数の定義は[[コチラ>#nb2b7282]]。
show_image_info(x_train, y_train_org, label, 1300)
-モデルの定義~
畳み込み層とプーリング層が3層、全結合層が2層の[[CNNモデル...
--input_shape:入力の[[テンソル>NumPy#h768806a]]の形
--filters:カーネル数=フィルター数=特徴マップ数
--kernel_size:カーネルのサイズ(辺のピクセル数
--strides:カーネルをスライドさせる際のピクセル数
--padding:画像の縁取り処理における縁取り幅(kernel_size=...
model = Sequential()
# 畳み込み層とプーリング層1
model.add(Conv2D(input_shape=(32, 32, 3), filters=64, ke...
# バッチ正規化の追加位置
model.add(MaxPool2D(pool_size=(2, 2))) # プーリング増
model.add(Activation('relu'))
# 畳み込み層とプーリング層2
model.add(Conv2D(filters=128, kernel_size=(4, 4), stride...
# バッチ正規化の追加位置
model.add(MaxPool2D(pool_size=(2, 2))) # プーリング増
model.add(Activation('relu'))
# 畳み込み層とプーリング層3
model.add(Conv2D(filters=128, kernel_size=(4, 4), stride...
# バッチ正規化の追加位置
model.add(MaxPool2D(pool_size=(2, 2))) # プーリング増
model.add(Activation('relu'))
model.add(Flatten())
# 全結合層1
model.add(Dense(512))
model.add(Activation('relu'))
# Dropoutの追加位置
# 全結合層2
model.add(Dense(5))
model.add(Activation('softmax'))
# コンパイル
model.compile(loss='categorical_crossentropy',
optimizer=SGD(0.01), # 学習率:0.01
metrics=['accuracy'])
-モデルの学習
batch_size = 500
n_epoch = 30
hist = model.fit(x_train_std , y_train,
validation_data=(x_test_std, y_test),
batch_size=batch_size,
epochs=n_epoch,
verbose=1)
-モデルの推論~
関数の定義は[[コチラ>#nb2b7282]]。
index = 10
show_image_info(x_train, y_train_org, label, index)
predict = model.predict(x_test_std[index].reshape(1, 32,...
answer = y_test_org[index]
print('predict: ', predict)
print('answer : ', answer)
if predict == answer:
print('正解')
else:
print('不正解')
-モデルの評価
--テストデータで評価~
[[コチラ>#bbaf9696]]と同じ。
--訓練データで評価
---[[コチラ>#bbaf9696]]と同じ。
---訓練不足であることが解る。
--混同行列を出力~
[[コチラ>#bbaf9696]]と同じ。
--メトリック表示~
[[コチラ>#bbaf9696]]と同じ。
--間違った画像の出力~
[[コチラ>#bbaf9696]]とホボ同じ。
index = (y_test_org != result)
for i, val in enumerate(index):
if val == True:
print('predict: ', result[i])
print('answer : ', y_test_org[i])
show_image_info(x_test, y_test_org, label, i)
-性能向上
--訓練不足を補う~
batch_size, epochs=n_epoch
--チューニングを行う
---[[過学習の抑止>#yb34decb]]
---[[画像の前処理>#o122ce57]]
---[[勾配降下法アルゴリズムの選択>データマイニング(DM)-...
---[[転移学習、ファイン・チューニング>#se734ba8]]
-その他の[[CNNモデル>ニューラルネットワーク#fb7864bd]]~
ググると色々出てくる。計算量から[[GPU>深層学習(deep lear...
**共通項 [#x6c0f300]
***画像やラベルの確認 [#nb2b7282]
-画像の一覧で概要を捉える。
-画像とラベルを確認する。
def show_image_info(x, y, label, index):
print(label[y[index]])
plt.imshow(x[index].astype(np.uint8))
plt.show()
-一致、不一致を確認
***CNNにおける過学習の解決 [#yb34decb]
-[[DNN一般の過学習の解決>データマイニング(DM)- Python -...
--データ正規化
--重みの初期化
--早期終了(early stopping)~
--バッチ正規化(Batch Normalization)~
--ドロップアウト(Dropout)~
-CNN限定の過学習の解決
--前述の「DNN一般の過学習の解決」を参照
--データ正規化(画像)~
[[主線中の「Xの画素を0.0-1.0の範囲に正規化」を参照>#g51e6...
--[[データ拡張(data augmentation)>#o122ce57]]~
--[[バッチ正規化(Batch Normalization)>#n1b78a93]](モデ...
同一ニューロン(CNNではチャネル)でバッチデータに跨って平...
--バッチサイズに依存しない正規化手法~
バッチサイズが大き過ぎると正規化の効果が低下する可能性が...
---レイヤー正規化~
単一データで、複数ニューロン(CNNではチャネル)に跨って平...
---インスタンス正規化~
同一ニューロン(CNNではチャネル)や特徴マップについてのみ...
---グループ正規化~
ニューロン(CNNではチャネル)をn個にグルーピングしレイヤ...
***画像の前処理(様々な変換処理) [#o122ce57]
[[OpenCV]]を使用する。
-lenna.pngの
--ダウンロード
url = 'https://upload.wikimedia.org/wikipedia/en/7/7d/Le...
request.urlretrieve(url, 'lenna.png')
--読込・確認
img = cv2.imread('lenna.png')
print(type(img))
print(img.shape)
plt.imshow(img) # OpenCVはBGR解釈なので青みがかる。
--変換して保存
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # RGB解釈に変...
plt.imshow(img) # 元のRGB解釈の色合いで表示される。
cv2.imwrite('new_lenna.jpg', img) # RGB解釈で保存
-様々な変換処理
--比較関数を定義
def diff_image_info(img1, img2):
print(img1.shape)
print(img2.shape)
plt.subplot(1, 2, 1)
plt.imshow(img1)
plt.subplot(1, 2, 2)
plt.imshow(img2)
--リサイズ~
学習に画像データを入力するときは画像のサイズを揃える。
img2 = cv2.resize(img, (224, 224))
diff_image_info(img, img2)
--切り抜き~
画像の一部を切り抜く処理はarrayのスライシングで実装。
---ピクセル
img2 = img[100:400,100:400,:]
diff_image_info(img, img2)
---比率
h, w, c = img.shape
img2 = img[:, int(w * (1/5)): int(w *(4/5)), :]
diff_image_info(img, img2)
--明るさ調整
---グレースケール化~
色の意味合いが低い場合、モノクロ画像に変換し計算量を減ら...
grayed = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
diff_image_info(img, grayed)
---2値化~
グレーを使わない白と黒の2色に変換。~
スクリーン・トーンと同様の表現で、更に計算量を減らす。~
th, binary = cv2.threshold(grayed, 125, 255, cv2.THRESH_...
diff_image_info(grayed, binary)
---平滑化~
画像をぼやかしノイズ(ガサつきなど)を取り除く。
blurred = cv2.GaussianBlur(binary, (11, 11), 0)
diff_image_info(binary, blurred)
---ヒストグラム平坦化~
画素値のヒストグラムが全体的に平になるように濃度変換する...
画像の明るさの範囲を引き伸ばすと明暗部分でも輪郭線が認識...
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
clahed = clahe.apply(grayed)
diff_image_info(grayed, clahed)
---Mean Subtraction~
0~1正規化と合わせた標準化のようなスケーリング処理~
BatchNormalizationのように共変量シフトを抑制できる。
img2 = x.astype('f')
img2 /= 255 # 0~1正規化
img2 -= np.mean(img2) # スケーリング
diff_image_info(img, img2)
※ img単位ではなくxに対して適用できる。
---画像のピクセル値の正規化
img2 = img.astype('f')
img2 -= img.min()# 最小値を引く
img2 /= img.max()# 最大値で割る
diff_image_info(img, img2)
※ img単位ではなくxに対して適用できる。
--[[データ拡張(data augmentation)>ニューラルネットワー...
---左右反転
flipped = cv2.flip(img, 1)
diff_image_info(img, flipped)
---回転~
・関数定義
def opencv_rotate(img, angle=30):
size = (img.shape[0], img.shape[1])
center = (int(size[0]/2), int(size[1]/2))
rotation_matrix = cv2.getRotationMatrix2D(center, an...
return cv2.warpAffine(img, rotation_matrix, size)
・回転実行
rotated = opencv_rotate(img, 30)
diff_image_info(img, rotated)
---並進~
・関数定義
def opencv_move(img, h=100, v=50):
rows, cols, channnels = img.shape
M = np.float32([[1,0,h],[0,1,v]])
return cv2.warpAffine(img, M, (cols, rows))
・並進実行
moved = opencv_move(img, 200, 100)
diff_image_info(img, moved)
---拡大(クロップ)~
画像サイズを変えずにズームする
・関数定義
def opencv_zoomin(img, h=2.0, v=2.0):
zoomed = cv2.resize(img, None, fx=h, fy=v)
height_1, width_1, channel_1 = img.shape
height_2, width_2, channel_2 = zoomed.shape
x = int((width_2 - width_1) / 2)
y = int((height_2 - height_1) / 2)
return zoomed[y:y+height_1, x:x+width_1]
・拡大実行
zoomed = opencv_zoomin(img, 2, 3)
diff_image_info(img, zoomed)
---ガンマ変換~
画像の明るさを全体的に明るく or 暗くする処理~
・関数定義
def opencv_gamma(img, gamma=0.5):
look_up_table = np.zeros((256, 1), dtype='uint8')
for i in range(256):
look_up_table[i][0] = 255 * pow(float(i) / 255, ...
return cv2.LUT(img, look_up_table)
・ガンマ変換
img_gamma = opencv_gamma(img, 0.3)
diff_image_info(img, img_gamma)
---ガウシアンノイズ~
画像の加工過程で発生する粒が散らばったようなノイズを加え...
・関数定義
def opencv_gaussian(img, loc=0.0, scale=5.0):
row, col, ch = img.shape
noise = np.random.normal(loc,scale,(row,col,ch))
noise = noise.reshape(row,col,ch)
noised = img + noise
noised /= 255
return noised
・ガウシアンノイズ
img_gaussian = opencv_gaussian(img, 50, 100)
diff_image_info(img, img_gaussian)
---色の三属性の調整~
・コントラスト(色相:hue)~
・ブライトネス(輝度:brightness)~
・カラフルネス(彩度:saturation)
-関数例~
get_changedとget_augmentedは別々に定義する。~
get_augmentedはtrainに対してのみ実行してtestに対しては実...
--バッチ変換
def get_changed(img):
# グレースケール化
...
# ヒストグラム平坦化
...
# 平滑化
...
# カラーでなくなっている場合、
# 次元が減っているので、追加する。
return blurred[:,:,np.newaxis]
--バッチ拡張
def get_augmented(img):
# 左右反転
if np.random.rand() > 0.5:
img = cv2.flip(img, 1)
# 左右度回転
if np.random.rand() > 0.5:
size = (img.shape[0], img.shape[1])
center = (int(size[0]/2), int(size[1]/2))
angle = np.random.randint(-45, 45) # -45 ~ +45 ...
rotation_matrix = cv2.getRotationMatrix2D(center...
img = cv2.warpAffine(img, rotation_matrix, size)
return img
plt.imshow(get_augmented(x_train[1300]).astype(np.uint8))
***[[転移学習>深層学習のテクニック#ebe9edcc]]、[[ファイン...
-全結合層部分を含まない学習済みモデルの読込
--weights :重みの初期値('random': ランダム, 'imagen...
--include_top :全結合層のダウンロード(True: する, False...
--input_tensor:入力[[テンソル>NumPy#h768806a]]の型(縦, ...
base_model = VGG16(weights='imagenet', include_top=False...
# inputs.output_shape => (None, 1, 1, 512)
-追加する全結合層部分を定義
n_class = 5
top_model = Sequential()
top_model.add(Flatten(input_shape=inputs.output_shape[1:...
top_model.add(Dense(256))
top_model.add(Activation('relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(n_class))
top_model.add(Activation('softmax'))
-全結合層部分を含まない学習済みモデルに全結合層部分を追加
model = Model(inputs=base_model.input, outputs=top_model...
-転移学習は既存部分を再学習しない、ファイン・チューニング...
--既存部分の畳み込み層のパラメタを再学習しないように固定...
# for layer in model.layers[:-last_few_layers]: # 先頭~...
# スライシングでモデルの15層目までのパラメタを固定
for layer in model.layers[:15]:
layer.trainable = False
--学習率を通常の 10^-2 倍程度に小さくする。
model.compile(loss='categorical_crossentropy',
optimizer=SGD(lr=0.0001),
metrics=['accuracy'])
-モデルの確認と試用
--確認
model.summary()
--前処理
---関数定義
def preprocess_vgg16(img):
# リサイズ
img= cv2.resize(img, (32, 32))
# RGBからそれぞれvgg指定の値を引く
# (mean-subtractionに相当)
img[:, :, 0] -= 103.939
img[:, :, 1] -= 116.779
img[:, :, 2] -= 123.68
return img
---前処理実行~
leakageの防止(データ分割後にデータ変換・拡張等)~
なお、get_augmented、get_changedについては[[画像の前処理>...
x_train_list = []
for img in x_train:
x_train_list.append(preprocess_vgg16(get_augmented(g...
x_train_aug = np.array(x_train_list)
x_test_list = []
for img in x_test:
x_test_list.append(preprocess_vgg16(get_augmented(ge...
x_test_aug = np.array(x_test_list)
--試用~
調整てfitを行う([[前述の手順>#n1b78a93]])。
batch_size = 100
n_epoch = 1 # 試用なので回数を減らす
-以下は、tensorflow_hubで学習済みResNetの転移学習の例。
import tensorflow as tf
import tensorflow_hub as hub
IMAGE_SIZE = (224, 224)
out_features = 10
model_handle = "https://tfhub.dev/google/bit/s-r50x3/1"
do_fine_tuning = False
do_dense_train = True
model = tf.keras.Sequential([
tf.keras.layers.InputLayer(input_shape=IMAGE_SIZE + (3...
hub.Keras.Layer(model_handle, trainable=do_fine_tuning),
tf.keras.layers.Dense(out_features, trainable=do_dense...
])
model.summary()
*参考 [#j26b50a4]
-作成中のコンテンツへのリンク - OSSコンソーシアム~
https://www.osscons.jp/joho108j0-537
**[[scikit-learn]] [#ucea6e4b]
**[[TensorFlow・Keras]] [#k4e2cb7b]
**[[畳み込みニューラルネットワーク(CNN)]] [#h89f95c3]
ページ名: