迁移学习:将一个领域的已经成熟的知识应用到其他的场景中,例如图像识别中最常见的例子,训练一个神经网络。来识别不同的品种的猫,你若是从头开始训练,你需要百万级的带标注数据,海量的显卡资源。而若是使用迁移学习,你可以使用Google发布的Inception或VGG16这样成熟的物品分类的网络,只训练最后的softmax层,你只需要几千张图片,使用普通的CPU就能完成,而且模型的准确性不差。
案例一
框架:keras
数据集:CIFAR10
模型:vgg16
注:vgg16模型的输入图像尺寸至少为 48*48
思路:去掉vgg16的顶层,保留其余的网络结构与训练好的权重。然后添加模型结构,进而训练CIFAR10。
1.模型结构
2.具体代码以及注释
①训练代码
# -*- coding: utf-8 -*-
#迁移学习,vgg16+cifar10
from keras.applications.vgg16 import VGG16
from keras.layers import Dense, Flatten, Dropout
from keras.models import Model
from keras.optimizers import Adam
from keras.datasets import cifar10
import cv2 #加载opencv,为了后期的图像处理
from keras import datasets
import h5py as h5py
import numpy as np
import matplotlib.pyplot as plt
import keras
from keras.utils import plot_model
import matplotlib.pyplot as plt
from keras.callbacks import ModelCheckpoint
ishape = 64
model_vgg = VGG16(include_top=False, weights='imagenet', input_shape=(ishape,ishape, 3))
for layers in model_vgg.layers:
layers.trainable = False
model = Flatten()(model_vgg.output)
model = Dense(4096, activation='relu',name='fc1')(model)
model = Dropout(0.5)(model)
model = Dense(4096, activation='relu',name='fc2')(model)
model = Dropout(0.5)(model)
model = Dense(10, activation='softmax',name='prediction')(model)
model_vgg_cifar10_pretrain = Model(inputs=model_vgg.input, outputs=model, name='vgg16_pretrain')
model_vgg_cifar10_pretrain.summary()
model_vgg_cifar10_pretrain.compile(optimizer='sgd', loss='categorical_crossentropy',
metrics=['accuracy'])
(X_train,y_train),(X_test,y_test) = cifar10.load_data()
X_train = [cv2.resize(i,(ishape,ishape)) for i in X_train]
X_test = [cv2.resize(i,(ishape,ishape)) for i in X_test]
X_train = np.concatenate([arr[np.newaxis] for arr in X_train] ).astype('float32')
X_test = np.concatenate([arr[np.newaxis] for arr in X_test] ).astype('float32')
print(X_train[0].shape)
print(y_train[0])
X_train = X_train/255
X_test = X_test/255
np.where(X_train[0] != 0)
#哑编码
def train_y(y):
y_one = np.zeros(10)
y_one[y] = 1
return y_one
y_train_one = np.array([train_y(y_train[i]) for i in range(len(y_train))])
y_test_one = np.array([train_y(y_test [i]) for i in range(len(y_test ))])
#迭代训练(注意这个地方要加入callbacks)
history=model_vgg_cifar10_pretrain.fit(X_train, y_train_one,
validation_data=(X_test, y_test_one),
epochs=100, batch_size=128,
validation_split=0.1,
verbose=1,
shuffle=True)
import matplotlib.pyplot as plt
fig = plt.figure()#新建一张图
plt.plot(history.history['acc'],label='training acc')
plt.plot(history.history['val_acc'],label='val acc')
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(loc='lower right')
fig.savefig('trans_VGG16'+'acc.png')fig = plt.figure()
plt.plot(history.history['loss'],label='training loss')
plt.plot(history.history['val_loss'], label='val loss')
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(loc='upper right')
fig.savefig('VGG16'+'loss.png')
model_vgg_cifar10_pretrain.save('transfer_cifar10.h5')
②识别代码
#-*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as processimage
from keras.models import load_model
from scipy import misc
import scipy
#load trained model
model = load_model('transfer_cifar10.h5') #导入模型
class MainPredictImg(object):
def __init__(self):
pass
def pre(self,filename):
pred_img = processimage.imread(filename)#read image
pred_img = np.array(pred_img) #transfer to array np
pred_img = scipy.misc.imresize(pred_img,size = (64, 64)) #将任意尺寸的图片resize成网络要求的尺寸
pred_img = pred_img.reshape(-1, 64, 64, 3)
prediction = model.predict(pred_img) #predict
labels = ['airplane','automobile','bird','cat','deer','dog','frog','horse','ship','truck']
Final_prediction = [result.argmax() for result in prediction][0]
Final_prediction = labels[Final_prediction]
a = 0
for i in prediction[0]:
print labels[a]
print 'Percent:{:.30%}'.format(i) # 30%输出小数点后30位
a = a+1
return Final_prediction
def main():
Predict = MainPredictImg()
res = Predict.pre('airplant.jpg') #导入要识别的图片
print 'your picture is :-->',res
if __name__ == '__main__':
main()
3.识别结果:
案例二
from keras.applications.vgg16 import VGG16
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.applications.vgg16 import preprocess_input
from keras.applications.vgg16 import decode_predictions
import keras
import tensorflow as tf
# 模型手动下载然后放到目录C:\Users\用户名\.keras\models下,下载地址如下:
# https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels.h5
# https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5
# 载入模型并打印
model = VGG16()
print(model.summary())
# 加载一副测试图片
image = load_img("dog.jpg", target_size=(224, 224))
# 转为数组
image = img_to_array(image)
# 重塑成4D
image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
# 预处理图片
image = preprocess_input(image)
# 预测
predict_result = model.predict(image)
# 解析预测结果
label = decode_predictions(predict_result)
# 打印出三个概率最大的分类
for idx in range(0, 3):
print("类别:%s 概率:%0.4f"%(label[0][idx][1], label[0][idx][2]))
# 清理
keras.backend.clear_session()
tf.reset_default_graph()
案例三
1、VGG19 + cifar10
# -*- coding:utf-8 -*-
import tensorflow as tf
import numpy as np
import time
import os
import sys
import random
import cPickle as pickle
class_num = 10
image_size = 32
img_channels = 3
iterations = 200
batch_size = 250
total_epoch = 164
weight_decay = 0.0003
dropout_rate = 0.5
momentum_rate = 0.9
log_save_path = './vgg_19_logs'
model_save_path = './model/'
def download_data():
dirname = 'cifar10-dataset'
origin = 'http://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz'
fname = './CAFIR-10_data/cifar-10-python.tar.gz'
fpath = './' + dirname
download = False
if os.path.exists(fpath) or os.path.isfile(fname):
download = False
print("DataSet already exist!")
else:
download = True
if download: