知识点介绍
(1)AEC-autoencoder自动编码器
AEC是由encoder和decoder两部分组成。input 和 output 的维度一致。AEC只是对数据feature set做一定的处理,用来重构数据,先把数据降维,然后再升维。AEC只需输入X_train,X_test。不需要输入Y数据。
因此,AEC的目的是:
- 数据去噪
- 为了进行可视化而降维度
【可以把多维度的数据降维成两个维度,然后再可视化check data】
(2)Fashion-MNIST data介绍
不同于 MNIST手写数据集,Fashion-MNIST数据集包含了10个类别的图像,分别是:t-shirt(T恤),trouser(牛仔裤),pullover(套衫),dress(裙子),coat(外套),sandal(凉鞋),shirt(衬衫),sneaker(运动鞋),bag(包),ankle boot(短靴)。数据集包含着10种类别的共7万个data。6万个train data和1万个test data。图像长度是28*28。
(3) Data preprocessing
下载data using tf
(Xtrain, y_train),(X_test,y_test)=tf.keras.datasets.fashion_mnist.load_data()
print(f'The shape of Train data: {Xtrain.shape}')
print(f'The shape of Test data :{X_test.shape}')
The shape of Train data: (60000, 28, 28)
The shape of Test data :(10000, 28, 28)
然后,我们需要从train data去选取最后5000个samples作为validation
X_train = Xtrain[:-5000,:,:] #从头开始 到 倒数5000个数据,共55000个samples
X_valid = Xtrain[-5000:,:,:] #从倒数5000个数据开始 到最后,共5000个samples
print(f'The shape of X_train: {X_train.shape}')
print(f'The shape of X_valid: {X_valid.shape}')
The shape of X_train: (55000, 28, 28)
The shape of X_valid: (5000, 28, 28)
然后需要对X数据进行rescale,把数据变成0-1.这样我们才能用tensorflow来处理数据。 这一步称为cast into tensorflow object。只要把所有X data除255.因为图像的数据最大值就是255.处于最大值即可把数据映射到0-1.
# cast into tensorflow object
X_train = tf.cast(X_train,dtype=tf.float32)/255.0
X_valid = tf.cast(X_valid,dtype=tf.float32)/255.0
X_test = tf.cast(X_test,dtype=tf.float32)/255.0
同时对y处理,y现在的值是整数,0-9。需要把y变成one hot array。比如y1=1,然后变成[0,1,0,0,0,0,0,0,0,0]。使用tf.one_hot函数来操作。
y_train, y_test = tf.one_hot(trainY, depth=10), tf.one_hot(testY, depth=10)
(4)model using keras Sequential API
使用keras Sequential API 来创建encoder和decoder。
create the encoder
#create the encoder
Encoder = tf.keras.Sequential([
#先扁平化,变成(N, depth*width)的维度,N是samples数,28*28=784
tf.keras.layers.Flatten(input_shape=(28,28)),
#从784降维到128,激活函数为relu
tf.keras.layers.Dense(128,activation='relu'),
#从128降维到64,激活函数为relu
tf.keras.layers.Dense(64,activation='relu')
])
create the decoder
#create the decoder
Decoder = tf.keras.Sequential([
#从64升维到128
tf.keras.layers.Dense(128, activation='relu'),
#从128升维到784,激活函数为sigmoid
tf.keras.layers.Dense(784, activation='sigmoid'),
#再把数据reshape为28*28
tf.keras.layers.Reshape((28,28))
])
把Encoder和Decoder结合一起便是AEC模型
#combine encoder and decoder together
Autoencoder = tf.keras.Sequential([
Encoder,
Decoder
])
Autoencoder.summary()
(5)compile model we create
规定几项指标:
- loss function用binary cross entropy
- Metric: 由于X data中,784的数都不是0或者1.为了计算binary accuracy,我们需要round每个数据为0或者1
- Optimizer: SGD with learning rate = 1.5
round数据的函数
def rounded_accuracy(y_true, y_pred):
return keras.metrics.binary_accuracy(tf.round(y_true), tf.round(y_pred))
#This is for metrics to round x data into 0, 1
运行model
Autoencoder.compile(
loss = tf.keras.losses.binary_crossentropy,
optimizer = tf.keras.optimizers.SGD(lr = 1.5),
metrics = [rounded_accuracy]
)
语法解释:语法结构为model.compile(loss=‘目标函数’, optimizer = optimizer, metrics = [‘accuracy’])
- 目标函数,也称为损失函数
损失函数,也就是计算函数损失的值,我们可以选mse,squared_hinge,binary_crossentropy,categorical_crossentrop等等。 - 优化器-optimizer
优化器很容易理解,就是选择常见的SGD, Adam, Momentum, RMSProp, Adagrad等等。Adam 是比较常见的一种类型。 - metrixs-性能评估
Accuracy 精确率,用于分类,Accuracy = (TP+TN)/(TP+TN+FP+FN)
CategoricalAccuracy 含义差不多。
# Early stopping based on a criterion - validation loss (generalization error) - regularization
early_stopping_cb = tf.keras.callbacks.EarlyStopping(patience=3,restore_best_weights=True)
#3是指3个epoch内没有improve,则停止训练。
对于Early Stopping的理解
Early Stopping 是callbacks的一种,callbacks就是指定每个epoch的开始和结束的操作。callbakcs有一些接口是,可以连接acc, val_acc, loss, val_loss。acc和loss是train data的acc和loss。而EarlyStopping则是用于提前停止训练的过程,比如,当训练时的loss不再减少时,停止训练或者减小的程度小于某阀值时,停止训练。
其中epoch的意思是过程中要遍历数据集多少次。如果epoch值太小,则模型可能是欠拟合。如果epoch值太大,则模型是过度拟合。
Early Stopping的使用是因为再继续训练下去会导致测试集的准确率下降。
一般来说,训练的过程是
- 将数据分成训练集和验证集
- 每个epoch结束之后,将会在验证集获取结果acc和loss,随着epoch的增加,如果验证记得loss增加,则停止训练
这种做法很符合常规做法,但是,有可能这个epoch之后,精度下降了或者loss升高了,但是有可能下个epoch,精度就上来了,我们不可能因为一两次的连续降低就停止了训练,所以我们要做的是,训练过程中,记录自己最好的验证集精度,经过10次epoch之后,仍没超过最佳精度,那么可以认为精度不能再提高了,则停止训练。这就是early stoppinh epoch的作用。
Early Stopping的参数
- patience: 能够容忍多少个epoch内精度没有提高的值
- monitor:数据接口,有acc, cal_acc,loss,val_loss
- min_delta:阀值设置,大于这个阀值才能算提高了精度。
设置好参数了,开始训练模型
history = Autoencoder.fit(X_train,X_train,batch_size=32,
epochs=100, #遍历100次数据集
validation_data = (X_valid,X_valid),
callbacks=[early_stopping_cb])
history.history里面包含着acc, valid_acc, loss, valid_loss四个参数。
画图
%matplotlib inline
import matplotlib.pyplot as plt
#Save the training history into dataframe
history_df = pd.DataFrame(history.history)
#plot the training history
plt.figure(figsize=(10,5))
plt.plot(history_df[['loss','val_loss']]);
plt.legend(['Train Loss','Valid Loss']);
plt.xlabel('Epochs');
plt.ylabel('Loss');
plt.title('History of the Losses');
#把前面5张图片显示出来
pred_images = AutoEncoder.predict(x_test[0:5,:,:])
fig, ax = plt.subplots(nrows=2,ncols=5,figsize= (15,10))
for i in range(len(prediction_result)):
ax[0,i].imshow(prediction_result[i,:,:],cmap='Greys')
ax[1,i].imshow(X_test[i,:,:],cmap='Greys')
ax[0,i].axis('off');
ax[1,i].axis('off');
ax[0,i].title.set_text('Prediciton {}'.format(i));
ax[1,i].title.set_text('Real {}'.format(i));
Conclusion: 看AEC模型把数据通过降维然后升维后得到的数据是能够去噪的。
(6)使用前面已经train好的encoder模型,用新的data来train后面的decoder参数。这次的模型用来分类
这次模型encoder跟前面一样,后面decoder变成Dense(30, Relu)->Dense(10,softmax)。这次是用来分类。
定义decoder模型的参数
#Initial the Classfication Layer
Classification_layers = tf.keras.Sequential([
tf.keras.layers.Dense(30,activation='relu'),
tf.keras.layers.Dense(10,activation='softmax')
])
把前面Encoder的参数跟新的decoder模型结合在一起
#combine the two sequential together
Encode_Classifier = tf.keras.Sequential([
Autoencoder.layers[0],
Classification_layers])
#freeze the weight for Encoder
Autoencoder.layers[0].trainable = False
#即不用训练Autoencoder.layers[0]这部分,只需要训练Classification_layers的参数即可。
新的data
用train data前面的3000个samples来训练模型。
#one hot encoding for training label
y_train = tf.one_hot(ytrain[:3000],depth=10)
X_train_subset = X_train[:3000]
compile 新模型
#compile the model using defined metrics, optimizer and loss
Encode_Classifier.compile(
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001),
metrics = [tf.metrics.CategoricalAccuracy()],
loss= tf.keras.losses.CategoricalCrossentropy()
)
训练新模型
classifier_callback = tf.keras.callbacks.EarlyStopping(patience=3,restore_best_weights=True)
classifier_history = Encode_Classifier.fit(X_train_subset,y_train,
epochs=100,batch_size=32,
validation_split=0.2,
callbacks = classifier_callback )
可视化loss
#plot the training losses and validation losses trend
classifier_history_df = pd.DataFrame(classifier_history.history)
plt.plot(classifier_history_df[['loss','val_loss']]);
plt.legend(['Train Loss','Validaiton Loss']);
plt.xlabel('Epochs')
plt.ylabel('Losses')
plt.title('Classifier Training Log');
计算分类模型的acc on test data
#make prediction
pred_test = np.argmax(Encode_Classifier.predict(X_test),axis=1) #np.argmax是返回最大值的位置,位置值就是预测的图片值
#y_test值没有经过one hot处理,还是整数值0-9
#calculate the accuracy
accuracy = np.mean(pred_test == y_test)
print(f'The accuracy for test data: {accuracy*100:.2f} %')
The accuracy for test data: 78.97 %