一.迁移学习的概述

迁移学习是指将一个在某领域完成学习任务的网络应用到新的领域来进行学习任务。
基于卷积网络实现迁移学习

对于已经训练完毕的网络模型来说,通常该网络模型的前几层学习到的是通用特征,随着网络层次的加深,更深次的网络层更偏重于学习特定的特征,因此可将通用特征迁移到其他领域。对于深度卷积网络来说,经过预训练的网络模型可以实现网络结构与参数信息的分离,在保证网络结构一致的前提下,便可以利用经过预训练得到的权重参数初始化新的网络,这种方式可以极大地减少训练时间。

具体步骤如下:

①选定基于ImageNet训练完毕的网络模型

②用自己搭建的全连接层替换所选定网络模型的全连接层,得到新网络模型。

③新网络模型中固定所需层数的参数,在新的小样本下训练余下参数。

④新网络模型训练完毕

这种方式又称为微调,上述步骤的训练避免了网络模型针对新任务从头开始训练网络的环节,可节省时间。基于ImageNet训练完毕的网络模型泛华能力非常强,无形中扩充了训练数据,使得新网络模型提升了训练精度,泛化能力更好,鲁棒性更好。
二.InceptionV3实现迁移学习

inceptionV3结构是从GoogleNet中的inception结构演变而来,相比传统的inception结构,inceptionv3有如下改进:

①将大的卷积核分解为小的卷积核,如用两个3*3的卷积核代替5*5的卷积核,卷积运算次数得到减少。

②在辅助分类器中增加BN层有助于提高精度,起到正则化的效果。

③将inception block 中最后一层中的stride 设置为2来实现feature map size 的衰减。

inceptionV3将基于微调的方式实现迁移学习,在获取基于ImageNet预训练完毕的inception v3模型后,用自己搭建的全连接层(包括输出层)代替inception V3模型的全连接层和输出层,得到一个新的网络模型,进而固定新网络模型的部分参数,使其不参与训练,基于mnist数据集训练余下未固定的参数。

代码实现:基于keras框架

from keras.datasets import mnist
from keras.applications.inception_v3 import InceptionV3
from keras.utils import np_utils
from keras.models import Model
from keras.layers import Dense,Dropout,Conv2D,MaxPooling2D,GlobalAveragePooling2D,Input,UpSampling3D
from matplotlib import pyplot as plt
import numpy as np
 
(X_train,Y_train),(X_test,Y_test)=mnist.load_data()
X_test1=X_test
Y_test1=Y_test
X_train=X_train.reshape(-1,28,28,1).astype("float32")/255.0
X_test=X_test.reshape(-1,28,28,1).astype("float32")/255.0
Y_test=np_utils.to_categorical(Y_test,10)
Y_train=np_utils.to_categorical(Y_train,10)
print(X_train.shape)
print(Y_train.shape)
 
#采用keras中函数api模型搭建新型网络即base_model
#weight="imagenet",xcception权重使用基于imagenet训练获得的权重,include_to=false代表不包含顶层的全连接层
base_model=InceptionV3(weights="imagenet",include_top=False)
input_inception=Input(shape=(28,28,1),dtype="float32",name="inceptionv3")
#对输入数据上采样
x=UpSampling3D(size=(3,3,3),data_format="channels_last")(input_inception)
#将数据送入model模型
x=base_model(x)
#此时模型没有全连接层,需要自己搭建全连接层
#通过GlobalAveragePooling2D对每张二维特征图进行全局平均池化,输出对应一维数值
x=GlobalAveragePooling2D()(x)
#搭建全连接层
x=Dense(1024,activation="relu")(x)
x=Dropout(0.5)(x)
pre=Dense(10,activation="softmax")(x)
#调用model模型,定义新的模型inceptionv3的输入层,输出层
inceptionv3_model=Model(inputs=input_inception,outputs=pre)
#打印base_model模型的各层名称和对应层数
for i,layer in enumerate(base_model.layers):
    print(i,layer.name)
#固定base_model前64层的参数使其不参与训练
for layer in base_model.layers[:64]:
    layer.trainable=False
#查看网络模型摘要
inceptionv3_model.summary()
 
#编译
inceptionv3_model.compile(
    loss="categorical_crossentropy",
    optimizer="adam",
    metrics=["accuracy"]
)
#训练
n_epoch=5
n_batches=64
training=inceptionv3_model.fit(
    X_train,
    Y_train,
    epochs=n_epoch,
    batch_size=n_batches,
    validation_split=0.2,
    verbose=1
)
#模型评估
test=inceptionv3_model.evaluate(X_test,Y_test,verbose=1)
print("误差:",test[0])
print("准确率:",test[1])
 
#画出inceptionv3_model模型的随时期epochs变化曲线
def plot_history(training_history,train,validation):
    plt.plot(training.history[train],linestyle="--",color="b")
    plt.plot(training.history[validation],linestyle="-",color="r")
    plt.title("training history")
    plt.xlabel("epochs")
    plt.ylabel("accuracy")
    plt.legend(["train","validation"],loc="lower right")
    plt.show()
plot_history(training,"accuracy","val_accuracy")
 
def plot_history1(training_history,train,validation):
    plt.plot(training.history[train],linestyle="--",color="b")
    plt.plot(training.history[validation],linestyle="-",color="r")
    plt.title("training history")
    plt.xlabel("epochs")
    plt.ylabel("loss")
    plt.legend(["train","validation"],loc="upper right")
    plt.show()
plot_history1(training,"loss","val_loss")
 
#预测
prediction=inceptionv3_model.predict(X_test)
 
#打印原图像
def plot_image(image):
    fig=plt.gcf()
    fig.set_size_inches(2,2)
    plt.imshow(image,cmap="binary")
    plt.show()
def pre_result(i):
    plot_image(X_test1[i])
    print("真实值:",Y_test[i])
    print("预测值:",np.argmax(prediction[i]))
pre_result(0)
pre_result(1)
pre_result(2)

 

Xception的概述

Xception是inception处于极端假设的一种网络结构。当卷积层试图在三维空间(两个空间维度和一个通道维度)进行卷积过程时,一个卷积核需要同时绘制跨通道相关性和空间相关性。

前面分享的inception模块的思想就是将这一卷积过程分解成一系列相互独立的操作,使其更为便捷有效。典型的inception模块假设通道相关性和空间相关性的绘制有效脱钩,而Xception的思想则是inception模块思想的一种极端情况,即卷积神经网络的特征图中的跨通道相关性和空间相关性的绘制可以完全脱钩。

Xception实现迁移学习也是基于微调的方式,和InceptionV3实现迁移学习一样,在获取基于imageNet预训练完毕的Xception模型后,用自己搭建的全连接层(包括输出层)代替xception模型的全连接层和输出层,进而得到一个新的网络模型,固定新网络模型的部分参数,使其不参与训练,基于mnist数据集训练余下未固定的参数。

Xception实现迁移学习

代码实现:

from keras.applications.xception import Xception
from keras.datasets import mnist
from keras.utils import np_utils
from keras.layers import Dense,GlobalAveragePooling2D,Dropout,Input,UpSampling3D
from keras.models import Model
from matplotlib import pyplot as plt
import numpy as np
 
(X_train,Y_train),(X_test,Y_test)=mnist.load_data()
X_test1=X_test
Y_test1=Y_test
X_train=X_train.reshape(-1,28,28,1).astype("float32")/255.0
X_test=X_test.reshape(-1,28,28,1).astype("float32")/255.0
Y_test=np_utils.to_categorical(Y_test,10)
Y_train=np_utils.to_categorical(Y_train,10)
 
#搭建xception模型
#weight="imagenet",xcception权重使用基于imagenet训练获得的权重,include_to=false代表不包含顶层的全连接层
base_model=Xception(weights="imagenet",include_top=False)
input_xception=Input(shape=(28,28,1),dtype="float32",name="xception imput")
#对数据进行上采样,沿着数据的3个维度分别重复size[0],size[1],size[2]
x=UpSampling3D(size=(3,3,3),data_format="channels_last")(input_xception)
#将数据送入网络
x=base_model(x)
#此时模型没有全连接层,需要自己搭建全连接层
#通过GlobalAveragePooling2D对每张二维特征图进行全局平均池化,输出对应一维数值
x=GlobalAveragePooling2D()(x)
x=Dense(1024,activation="relu")(x)
x=Dropout(0.5)(x)
pre=Dense(10,activation="softmax")(x)
#调用Model,定义一个新的模型Xception_model
xception_model=Model(inputs=input_xception,outputs=pre)
#查看每一层的名称和对应的层数
for i,layer in enumerate(base_model.layers):
    print(i,layer.name)
#固定base_model中前36层的参数,使其不参与训练
for layer in base_model.layers[:36]:
    layer.trainable=False
#查看模型的摘要
xception_model.summary()
#编译
xception_model.compile(
    loss="categorical_crossentropy",
    optimizer="adam",
    metrics=["accuracy"]
)
#训练
training=xception_model.fit(
    X_train,
    Y_train,
    epochs=5,
    batch_size=64,
    validation_split=0.2,
    verbose=1
)
 
test=xception_model.evaluate(X_test,Y_test)
print("误差:",test[0])
print("准确值:",test[1])
 
#画出训练集和验证集的随着时期的变化曲线
def plot_history(training_history,train,validation):
    plt.plot(training.history[train],linestyle="-",color="b")
    plt.plot(training.history[validation],linestyle="--",color="r")
    plt.title("xception_model accuracy")
    plt.xlabel("epochs")
    plt.ylabel("accuracy")
    plt.legend(["train","validation"],loc="lower right")
    plt.show()
plot_history(training,"accuracy","val_accuracy")
def plot_history1(training_history,train,validation):
    plt.plot(training.history[train],linestyle="-",color="b")
    plt.plot(training.history[validation],linestyle="--",color="r")
    plt.title("xception_model accuracy")
    plt.xlabel("epochs")
    plt.ylabel("loss")
    plt.legend(["train","validation"],loc="upper right")
    plt.show()
plot_history1(training,"loss","val_loss")
 
#预测值
prediction=xception_model.predict(X_test)
#打印图片
def plot_image(image):
    fig=plt.gcf()
    fig.set_size_inches(2,2)
    plt.imshow(image,cmap="binary")
    plt.show()
def result(i):
    plot_image(X_test1[i])
    print("真实值:",Y_test1[i])
    print("预测值:",np.argmax(prediction[i]))
result(0)
result(1)

————————————————
版权声明:本文为CSDN博主「无尽的沉默」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/hgnuxc_1993/article/details/116020911

posted on 2022-01-17 18:28  风生水起  阅读(76)  评论(0编辑  收藏  举报