在這篇文章中,將教你們實現一個網頁應用程序,該程序能夠接收狗的圖片,而後輸出其品種,其準確率超過80%!
咱們將使用深度學習來訓練一個識別狗品種的模型,數據集是狗圖像與他們的品種信息,經過學習圖像的特徵來區分狗的品種。
數據分析
數據集能夠從這裏下載(https://s3-us-west-1.amazonaws.com/udacity-aind/dog-project/dogImages.zip)。如下是關於數據的一些介紹:html
from keras.preprocessing import image
from tqdm import tqdmpython
def path_to_tensor(img_path):
'''將給定路徑下的圖像轉換爲張量'''
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
return np.expand_dims(x, axis=0)web
def paths_to_tensor(img_paths):
'''將給定路徑中的全部圖像轉換爲張量'''
list_of_tensors = [path_to_tensor(img_path) for img_path in tqdm(img_paths)]
return np.vstack(list_of_tensors)算法
最後,咱們使用ImageDataGenerator對圖像進行動態縮放和加強
train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255,
horizontal_flip=True,
vertical_flip=True,
rotation_range=20)flask
valid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255.)數組
test_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1./255.)網絡
train_generator = train_datagen.flow(train_tensors, train_targets, batch_size=32)
valid_generator = train_datagen.flow(valid_tensors, valid_targets, batch_size=32)
test_generator = train_datagen.flow(test_tensors, test_targets, batch_size=32)
CNNapp
咱們將在預處理數據集上從頭開始訓練卷積神經網絡(CNN),以下所示:
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(224, 224, 3)),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Conv2D(256, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(2048, activation='softmax'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(1024, activation='softmax'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(133, activation='softmax')
])框架
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])機器學習
checkpointer = tf.keras.callbacks.ModelCheckpoint(filepath='../saved_models/weights_best_custom.hdf5',
verbose=1, save_best_only=True)
model.fit(train_generator, epochs=5, validation_data=valid_generator, callbacks=[checkpointer])
咱們使用一個ModelCheckpoint的回調來保存驗證分數較高的模型。經過測試模型,咱們獲得的準確率只有1%左右 **使用遷移學習** 如今,咱們使用遷移學習來實現更高的準確率。首先咱們下載ResNet-50,能夠經過運行下面的代碼來提取相應的訓練集、測試和驗證集:
bottleneck_features = np.load('Data/bottleneck_features/DogResnet50Data.npz')
train_Resnet50 = bottleneck_features['train']
valid_Resnet50 = bottleneck_features['valid']
test_Resnet50 = bottleneck_features['test']
咱們如今再次定義模型,並對提取的特徵使用GlobalAveragePooling2D,它將一組特徵平均爲一個值。最後,若是驗證損失在兩個連續的epoch內沒有增長,咱們使用額外的回調來下降學習率;若是驗證損失在連續的5個epoch內沒有增長,能夠提早中止訓練。
Resnet50_model = tf.keras.models.Sequential()
Resnet50_model.add(tf.keras.layers.GlobalAveragePooling2D(input_shape=train_Resnet50.shape[1:]))
Resnet50_model.add(tf.keras.layers.Dense(1024, activation='relu'))
Resnet50_model.add(tf.keras.layers.Dense(133, activation='softmax'))
Resnet50_model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
checkpointer = tf.keras.callbacks.ModelCheckpoint(filepath='saved_models/weights_best_Resnet50.hdf5',
verbose=1, save_best_only=True)
early_stopping = tf.keras.callbacks.EarlyStopping(patience=5, monitor='val_loss')
reduce_lr = tf.keras.callbacks.ReduceLROnPlateau(patience=2, monitor='val_loss')
Resnet50_model.fit(train_Resnet50, train_targets,
validation_data=(valid_Resnet50, valid_targets),
epochs=50, batch_size=20, callbacks=[checkpointer, early_stopping, reduce_lr], verbose=1)### 訓練模型
最後在測試集上的準確率爲82.65%,這與咱們白手起家訓練的模型相比,是一個巨大的進步。 **構建web應用程序** 對於web應用程序,咱們首先編寫了一個helper函數,該函數接受圖像路徑並返回品種。label_to_cat字典將每一個數字標籤映射到它的狗品種。
def predict_breed(img_path):
'''預測給定圖像的品種'''
bottleneck_feature = extract_Resnet50(path_to_tensor(img_path)) bottleneck_feature = tf.keras.models.Sequential([ tf.keras.layers.GlobalAveragePooling2D(input_shape=bottleneck_feature.shape[1:]) ]).predict(bottleneck_feature).reshape(1, 1, 1, 2048) # 得到預測向量 predicted_vector = Resnet50_model.predict(bottleneck_feature) # 模型預測的犬種 return label_to_cat[np.argmax(predicted_vector)]
對於web應用程序,咱們將使用flaskweb框架來幫助咱們用最少的代碼建立web應用程序。咱們定義一個接受圖像的路由,並用狗的品種呈現一個輸出模板
@app.route('/upload', methods=['POST','GET'])
def upload_file():
if request.method == 'GET':
return render_template('index.html')
else:
file = request.files['image']
full_name = os.path.join(UPLOAD_FOLDER, file.filename)
file.save(full_name)
dog_breed = dog_breed_classifier(full_name)
return render_template('predict.html', image_file_name = file.filename, label = dog_breed)
predict.html是分別顯示圖像及其犬種的模板。 **結論** 祝賀你!你已經成功地實現了一個狗品種分類器,而且能夠準確地分辨出狗的品種。讓咱們總結一下咱們在這裏學到的知識: 1. 咱們對數據集進行了分析和預處理。機器學習算法須要單獨的訓練集、測試集和驗證集來進行置信預測。 1. 咱們從零開始使用CNN,因爲未能提取特徵,因此表現不佳。 1. 而後咱們使用了遷移學習,準確度大大提升 1. 最後,咱們構建了一個Flask web應用程序來實現咱們的項目封裝 咱們確實學到了不少東西,但你還能夠嘗試不少其餘的事情。你能夠在heroku上部署web應用程序,也能夠嘗試使用不一樣的層(如Dropout層)來提升準確性。 參考連接:https://towardsdatascience.com/dont-know-the-breed-of-your-dog-ml-can-help-6558eb5f7f05