環境構成
Python 3.6
scikit-image 0.17.2
numpy 1.19.0 opencv
-python 3.4.2.16 opencv
-contrib-python 3.4.2.16
プログラムの進捗状況
トレーニングデータを読む
train_datagen = ImageDataGenerator(rescale=1./255,
rotation_range = 45,
width_shift_range = 0.2,
height_shift_range = 0.2,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip=True)
train_gen = train_datagen.flow_from_directory("data/train",
target_size = (240, 240),
batch_size = 8,
class_mode="categorical")
ImageDataGenerator
データ拡張が可能です;
参照リンク:Keras ImageDataGenerator
- 再スケール:0から255までの値を0から1の間の値に正規化します。
- rotation_range:整数、画像のランダムな回転角、値は[0、180]、デフォルトは通常反時計回りだと思います。
- width_shift_range:浮動小数点数、特定の比率、画像のランダムな水平シフトの範囲、値は[0、1]です。
- height_shift_range:浮動小数点数、特定の比率、画像のランダムな垂直移動の振幅、値は[0、1]です。
- せん断範囲:(反時計回りの)せん断変換の程度を示す浮動小数点数。
- zoom_range:ランダムズームの程度を示す浮動小数点数、または[下、上]の形式のリスト。
- Horizontal_flip:ブール値、ランダムな水平フリップ。
フォルダに従って画像を自動的に分類します。
flow_from_directory
フォルダごとに番号を付けて自動的に分類できます。
トレーニングデータをバッチで表示します。バッチには8つの画像があり、temp [0]は画像、temp [1]はラベル、
データ範囲は0〜1です。:ワン
ホットエンコーディングが完了しました:
事前にトレーニングされたモデルをオンラインでロードする
VGG = keras.applications.vgg16.VGG16(weights="imagenet", include_top=False, input_shape=[240, 240, 3])
または、ローカルにアクセスしたファイルをロードします。
from keras.models import load_model
VGG = load_model("model/VGG_Pretrained.h5")
モデル情報の表示:
モデルの最後に分類子を追加します
from keras.layers import Dense, Flatten
x = VGG.layers[-1].output
x = Flatten()(x)
x = Dense(64, activation="sigmoid")(x)
predictions=Dense(5, activation="softmax")(x)
model = keras.Model(inputs=VGG.inputs, outputs=predictions)
モデルの背後に分類器を追加します。出力層のニューロンの数はラベルと同じである必要があります。平坦化を追加する必要があります。そうしないと、密層は行列入力を受け入れることができません。
簡単に言うと、ニューロンの2つの層が追加されます。より厄介なのは、元のモデルを接続することです。
for layer in model.layers[:-2]:
layer.trainable=False
最後の2つのレイヤーのみをトレーニングします。
オプティマイザーを定義する
adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8)
model.compile(loss="categorical_crossentropy", optimizer=adam, metrics=["accuracy"])
トレーニングモデル
model.fit_generator(train_gen, steps_per_epoch=12, epochs=10)
トレーニング済みモデルを保存します。
テストデータをロードする
import skimage.io as io
import skimage.transform as transform
img = io.imread("data/test/3.jpg")
img = img/255
img = transform.resize(img, output_shape=[240, 240])
print(img.shape)
plt.imshow(img)
テストを開始します。
indices = {'紫葡萄': 0, '红苹果': 1, '绿葡萄': 2, '黄苹果': 3, '黄香蕉': 4}
output = model.predict(img.reshape([1, 240, 240, 3]))
print(output)
出力結果
output_rには2つの数値があり、それぞれ予測結果の行数と列数を示します。
完全なソースコード
冗長な出力情報はありません
# 完整版
import numpy as np
import keras
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.optimizers import Adam
from keras.utils.np_utils import to_categorical
from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale=1./255,
rotation_range = 45,
width_shift_range = 0.2,
height_shift_range = 0.2,
shear_range = 0.2,
zoom_range = 0.2,
horizontal_flip=True)
train_gen = train_datagen.flow_from_directory("data/train",
target_size = (240, 240),
batch_size = 8,
class_mode="categorical")
# 从网上下载预先存取好的模型
VGG = keras.applications.vgg16.VGG16(weights="imagenet", include_top=False, input_shape=[240, 240, 3])
# 或者直接从本地导入
# from keras.models import load_model
# VGG = load_model("model/VGG_Pretrained.h5")
# 在原模型末尾加入分类器
from keras.layers import Dense, Flatten
x = VGG.layers[-1].output
x = Flatten()(x)
x = Dense(64, activation="sigmoid")(x)
predictions=Dense(5, activation="softmax")(x)
model = keras.Model(inputs=VGG.inputs, outputs=predictions)
# 设置为只需要训练最后新加入的两层神经元
for layer in model.layers[:-2]:
layer.trainable=False
# 定义优化器
adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8)
model.compile(loss="categorical_crossentropy", optimizer=adam, metrics=["accuracy"])
# 训练模型
model.fit_generator(train_gen, steps_per_epoch=12, epochs=10)
# 载入测试数据
import skimage.io as io
import skimage.transform as transform
img = io.imread("data/test/3.jpg")
img = img/255
img = transform.resize(img, output_shape=[240, 240])
# print(img.shape) # 查看图片信息
# plt.imshow(img)
# 结果展示
indices = {'紫葡萄': 0, '红苹果': 1, '绿葡萄': 2, '黄苹果': 3, '黄香蕉': 4}
output = model.predict(img.reshape([1, 240, 240, 3]))
# print(output)
# 使得结果更加清晰
output_r = np.where(output==np.max(output))
print(np.max(output_r[1])) # 表示预测结果的列编号