TensorFlow
- 因为此教程较基础,因此适用于各种版本的tensorflow,无需为此文章安装特定版本。
- TensorFlow的kersa模块中,有datasets模块,里面有常用的一些数据集。
import tensorflow as tf
from tensorflow import kersa
from tensorflow.kersa import datasets
(x_train, y_train),(x_test, y_test) = datasets.cifar10.load_data()
# cifar10 指的是数据有10种结果。
# 常将其转化为独热编码
num_classes = 10
# 设置独热编码的数量
y_train_onehot = keras.utils.to_categorical(y_train, num_classes)
y_test_onehot = keras.utils.to_categorical(y_test, num_classes)
- 图像标签是一个列表,将其映射为一个字符串。
# 给10个标签写上名字
category_dict = {0:'airplane',1:'automobile',2:'bird',3:'cat',4:'deer',5:'dog',
6:'frog',7:'horse',8:'ship',9:'truck'}
- 像素归一化(常用)
x_train = x_train.astype('float32')/255
x_test = x_test.astype('float32')/255
- 构建CNN模型,需要使用到的库有
tensorflow.kersa.Sequential
(用于叠加层(隐藏层或输出层))、tensorflow.kersa.layers
,需要tensorflow.kersa.layers
中的卷积层、激活函数、池化层、正则化等
from tensorflow.kersa import layers, Sequential
from tensorflow.kersa.layers import Conv2D,Activation,MaxPooling2D,Dropout,Flatten,Dense
- 定义函数,参数为训练集输入的维度,即
x_train.shape[1:]
,在函数中,使用Sequential()函数生成模型。
def CNN_classification_model(input_size = x_train.shape[1:]):
model = Sequential()
- Sequential()生成的模型可以使用add()方法添加层数。
model.add(Conv2D(32,(3,3),padding = 'same',input_shape=input_size))
model.add(Activation('relu'))
# 常用的有relu、tanh、sigmoid、softmax等
# 这里使用一个卷积层和一个激活函数构成了一个隐藏层。
对于函数Conv2D()的参数说明:
添加层数,参数是层的类型,在import到的函数可以看到有多种类型,这里是选择Conv2D,即卷积层。
参数一(64): filters
卷积核个数的变化,filters 影响的是最后输入结果的的第三个维度的变化,例如,输入的维度是 (600, 600, 3), filters 的个数是 64,转变后的维度是 (600, 600, 64).
参数二((3,3)):kernel_size
表示卷积核的大小,可以直接写一个数,影响的是输出结果前两个数据的维度。
参数三(padding):padding
是否对周围进行填充,"same"
即使通过kernel_size 缩小了维度,但是四周会填充 0,保持原先的维度;"valid"
表示存储不为0的有效信息。
未使用的参数:stride
, 步长,会影响卷积后的维度。
- 继续添加层:
#Conv2
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2),strides =1))
#第二个模块
model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
接下来,需要加入全连接层。
全连接层,是每一个结点都与上一层的所有结点相连,用来把前边提取到的特征综合起来。简单理解为,在输出层之前,应当有一个全连接层。
- 接入全连接层
# 需要先通过Flatten接入全连接层,直接add()一个Flatten层即可。
model.add(Flatten())
# 接入全连接层Dense
model.add(Dense(128))
# 同样的,全连接层也要有激活函数
model.add(Activation('relu'))
Dense()函数参数一(128):units
:代表该层的输出维度或神经元个数, units解释为神经元个数为了方便计算参数量,解释为输出维度为了方便计算维度.
- 进行正则化防止过拟合,使用Dropout:
#dropout层参数在0~1之间
model.add(Dropout(0.25))
# 接入输出层,输出层也是全连接层,输出维度是结果的可能个数,即num_classes
model.add(Dense(num_classes))
# 多分类问题,使用softmax函数
model.add(Activation('softmax'))
- 选择优化器
opt = keras.optimizers.Adam(learning_rate=0.0001)
优化器是指,在反向传播时,指导传播方向的方法。使得更新后的各个参数让损失函数(目标函数)不断逼近全局最小。除了Adam,还有SGD、Momentum、RMSprop等。
- 定义模型训练方法
model.compile(loss='sparse_categorical_crossentropy', optimizer=opt, metrics=['accuracy'])
# 参数一(loss): 损失函数(目标函数)。部分可选为:
# binary_crossentropy(亦称作对数损失,logloss)
# categorical_crossentropy:亦称作多类的对数损失,注意使用该目标函数时,需要将标签转化为形如(nb_samples, nb_classes)的独热编码
# sparse_categorical_crossentrop:如上,但接受稀疏标签。注意,使用该函数时仍然需要你的标签与输出值的维度相同.
# kullback_leibler_divergence:从预测值概率分布Q到真值概率分布P的信息增益,用以度量两个分布的差异.
# cosine_proximity:即预测值与真实标签的余弦距离平均值的相反数
# 参数二(optimizer): 选择反向传播的优化器
# 参数三(metrics): 准确率计算方式,附图。
# 这里输入是一个确定的数值(10种可能中的一种), 预测结果也是一个确定的数值,即选用accuracy参数。
附上loss的可选参数:
在keras官网上有loss的参数列表,这里放上截图,实际用法可在官网查询。
参数三的可选参数:
- 将训练一次后的模型返回
return model
- 定义模型。
model=CNN_classification_model()
model.summary()
- 模型训练
- 调用tensorflow.kersa.callbacks.ModelCheckPoint函数,以一定的频率保存keras模型或参数,通常是和model.compile()、model.fit()结合使用的,可以在训练过程中保存模型,也可以再加载出来训练一般的模型接着训练。
from tensorflow.keras.callbacks import ModelCheckpoint
# 保存训练好的模型参数
model_name = "final_cifar10.h5"
model_checkpoint = ModelCheckpoint(model_name, monitor='loss',verbose=1, save_best_only=True)
# 参数一:filepath,保存路径
# 参数二:评估指标,用于评估正确率的指标
# 参数三:保存模型的时候是否打印信息,1为是,0为否。
# 参数四:是否只保存最佳结果。
- 加载预训练模型
trained_weights_path = 'cifar10_weights.h5'
if os.path.exists(trained_weights_path):
model.load_weights(trained_weights_path,by_name=False)
- 训练模型
model.fit(x_train,y_train, batch_size=32, epochs=10,callbacks = [model_checkpoint],verbose=1)
# 参数epoch:最大迭代次数
# 参数callbacks:保存训练信息
# verbose:训练过程打印信息。
- 模型评估
model.evaluate(x_test, y_test, verbose=1)
- 输出每一类的预测结果
# 这里使用new_model,也可以是model,不过要给model调用load_weights函数,用于输出预测结果。
new_model = CNN_classification_model()
new_model.load_weights('final_cifar10.h5')
new_model.predict(x_test[0:1])
# 输出预测结果
new_model.predict_classes(x_test[0:1])
- 将模型参数保存下来(注意,这里保存的是未训练的模型)
model.save('./final_CNN_model.h5')
- 从文件中读取保存的模型
new_model = tf.keras.models.load_model('final_CNN_model.h5')
- 要读取训练好的模型,使用
model.fit()
参数里面的callback中保存的那个文件。在这里,即是ModelCheckpoint里面的model_name。
trained_model = CNN_classification_model()
trained_model.load_weight(model_path)
# 注意,这里是load_weight而不是load_model