作业15

补交:6.逻辑回归 https://www.cnblogs.com/Roromiya/p/13088857.html

一、手写数字数据集

  • from sklearn.datasets import load_digits
  • digits = load_digits()
1 # 1 - Load dataset
2 digits = load_digits()
3 X = digits['images']
4 Y = digits['target']

二、图片数据预处理

  • x:归一化MinMaxScaler()
  • y:独热编码OneHotEncoder()或to_categorical
  • 训练集测试集划分
  • 张量结构

使用自定义归一化函数normalization(),与独立热编码函数onehot_encode()

 1 # 2.1 - Reshape the images, from (8, 8) to (8, 8, 1)
 2 def img_reshape(images):
 3     return [tf.reshape(image, (8, 8, 1)).numpy() for image in images]
 4 X = img_reshape(X)
 5 
 6 # 2.2 - Normalize the images, scale the value to 0.0 ~ 1.0
 7 def normalization(data):
 8     _range = np.max(data) - np.min(data)
 9     return (data - np.min(data)) / _range
10 X = normalization(X)
11 
12 # 2.3 - Onehot encoding on labels
13 def onehot_encode(labels):
14     onehot_labels = []
15     for y in labels:
16         label = [0. for i in range(10)]
17         label[y] = 1.
18         onehot_labels.append(label)
19     return onehot_labels
20 def onehot_decode(labels):
21     return np.array([label.index(True) for label in labels.tolist()])
22 Y = onehot_encode(Y)
23 Y = np.array(Y)
24 
25 # 2.4 - Split the train-set and test-set
26 X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0)
27 
28 print('Images shape: ', X.shape)
29 print('Labels shape: ', Y.shape)
30 print('Images: ', X)
31 print('Labels: ', Y)

处理后的数据集尺寸(数量, 高度, 宽度, 通道数):

处理后的标签集尺寸(数量, 类别个数):

查看数据集:

查看标签集:

三、设计卷积神经网络结构

  • 绘制模型结构图,并说明设计依据。

网络结构:

 

设计依据:

1)数据尺寸太小,特征较少,没必要使用过深的网络提取特征,三层就够了。

2)由于图像尺寸较小,故卷积核尺寸设置为2×2,三个卷积-池化层的卷积核数量分别设置为32、64、128。

3)该模型不使用Dropout,因为在使用小卷积核时Dropout丢弃过多特征会导致准确率变差。

4)在卷积层后使用BatchNormalization替代Dropout,BN同样可以起到防止过拟合的作用,还可以加速模型收敛。

5)池化前使用ReLu而不是sigmod作为激活函数,目的是避免“梯度消失”。

6)由于这是一个用于分类的神经网络,独热编码值介于0.0~1.0之间,故全连接之后使用Softmax激活函数进行分类。

创建模型:

设置初始学习率为1e-4,优化器为Adam,损失函数为交叉熵损失

 1 def CNN():
 2     nn = models.Sequential()
 3     # 1st Convolution->BN->ReLu->Pool
 4     nn.add(layers.Conv2D(filters=32, kernel_size=(2, 2), input_shape=(8, 8, 1)))
 5     nn.add(layers.BatchNormalization())
 6     nn.add(layers.ReLU())
 7     nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=1))
 8 
 9     # 2nd Convolution->BN->ReLu->Pool
10     nn.add(layers.Conv2D(filters=64, kernel_size=(2, 2)))
11     nn.add(layers.BatchNormalization())
12     nn.add(layers.ReLU())
13     nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=1))
14 
15     # 3rd Convolution->Convolution->BN->ReLu->Pool
16     nn.add(layers.Conv2D(filters=128, kernel_size=(2, 2)))
17     nn.add(layers.Conv2D(filters=128, kernel_size=(2, 2)))
18     nn.add(layers.BatchNormalization())
19     nn.add(layers.ReLU())
20     nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=2))
21 
22     # Flatten->Dense->Softmax
23     nn.add(layers.Flatten())
24     nn.add(layers.Dense(units=10))
25     nn.add(layers.Softmax())
26     
27     # Compile and ready to use
28     nn.compile(
29         optimizer=optimizers.Adam(learning_rate=0.0001),
30         loss=losses.categorical_crossentropy,
31         metrics=['accuracy']
32     )
33     return nn

四、模型训练

设置batch_size为4,epoch为80轮。

创建回调函数TensorBoard(),用于记录loss下降曲线。

创建回调函数ReduceLROnPlateau(),当验证集超过10个epoch不下降时自动降低学习率。

def train(nn, train_image, train_label, test_image, test_label, batch_size, epoch, log_path):
    # Create Tensorboard callback
    tb = tf.keras.callbacks.TensorBoard(log_dir=log_path, histogram_freq=1)
    # Create learning rate reducer
    reduce_lr = ReduceLROnPlateau(monitor='val_loss', patience=10, mode='auto')
    history = nn.fit(train_image, train_label,
              batch_size=batch_size, epochs=epoch, validation_data=(test_image, test_label), callbacks=[tb, reduce_lr])
    return history

log_dir = "./logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
train(model, X_train, Y_train, X_test, Y_test, batch_size=4, epoch=80, log_path=log_dir)
model.save("./weights.hdf5") # Save the weights

训练过程:

Linux终端内启动tensorboard

打开Tensorboard网页界面,观察loss_epoch曲线、accuracy_epoch曲线:

  

打开Tensorboard网页界面,观察全连接层的张量直方图:

五、模型评价

  • model.evaluate()
  • 交叉表与交叉矩阵
  • pandas.crosstab
  • seaborn.heatmap

使用model.evaluate()进行模型评估:

1 # 5.1 - model.evaluate()
2 model.load_weights(args.weights)
3 print("\nModel Evaluate:")
4 model.evaluate(X_test, Y_test, batch_size=128)

评估结果——模型在测试集上的准确率为 99.72%

绘制交叉表:

1 # 5.2 - pandas.crosstab()
2 pred = model.predict_classes(X_test)
3 table = pandas.DataFrame(pandas.crosstab(onehot_decode(Y_test), pred, rownames=['true'], colnames=['pred']))
4 heatmap(table, annot=True, cmap="Reds", linewidths=0.2, linecolor='G')
5 plt.show()

 

 

完整代码:

Python版本:3.8.3

Tensorflow版本:2.2.0

Tensorboard版本:2.2.2

  1 import datetime
  2 import argparse
  3 from sklearn.datasets import load_digits
  4 from sklearn.model_selection import train_test_split
  5 import tensorflow as tf
  6 from tensorflow.keras import layers, models, optimizers, losses
  7 import numpy as np
  8 import os
  9 import pandas
 10 from seaborn import heatmap
 11 from matplotlib import pyplot as plt
 12 
 13 # From [9] to [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.]
 14 from tensorflow.python.keras.callbacks import ReduceLROnPlateau
 15 
 16 
 17 def onehot_encode(labels):
 18     onehot_labels = []
 19     for y in labels:
 20         label = [0. for i in range(10)]
 21         label[y] = 1.
 22         onehot_labels.append(label)
 23     return onehot_labels
 24 
 25 # From [0., 0., 0., 0., 0., 0., 0., 0., 1., 0.] to [9]
 26 def onehot_decode(labels):
 27     return np.array([label.index(True) for label in labels.tolist()])
 28 
 29 # Scale to 0. ~ 1.
 30 def normalization(data):
 31     _range = np.max(data) - np.min(data)
 32     return (data - np.min(data)) / _range
 33 
 34 # From (n, 8, 8) to (n, 8, 8, 1)
 35 def img_reshape(images):
 36     return [tf.reshape(image, (8, 8, 1)).numpy() for image in images]
 37 
 38 def CNN():
 39     nn = models.Sequential()
 40     # 1st Convolution->BN->ReLu->Pool
 41     nn.add(layers.Conv2D(filters=32, kernel_size=(2, 2), input_shape=(8, 8, 1)))
 42     nn.add(layers.BatchNormalization())
 43     nn.add(layers.ReLU())
 44     nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=1))
 45 
 46     # 2nd Convolution->BN->ReLu->Pool
 47     nn.add(layers.Conv2D(filters=64, kernel_size=(2, 2)))
 48     nn.add(layers.BatchNormalization())
 49     nn.add(layers.ReLU())
 50     nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=1))
 51 
 52     # 3rd Convolution->Convolution->BN->ReLu->Pool
 53     nn.add(layers.Conv2D(filters=128, kernel_size=(2, 2)))
 54     nn.add(layers.Conv2D(filters=128, kernel_size=(2, 2)))
 55     nn.add(layers.BatchNormalization())
 56     nn.add(layers.ReLU())
 57     nn.add(layers.MaxPool2D(pool_size=(2, 2), strides=2))
 58 
 59     # Flatten->Dense->Softmax
 60     nn.add(layers.Flatten())
 61     nn.add(layers.Dense(units=10))
 62     nn.add(layers.Softmax())
 63 
 64     # Compile and ready to use
 65     nn.compile(
 66         optimizer=optimizers.Adam(learning_rate=0.0001),
 67         loss=losses.categorical_crossentropy,
 68         metrics=['accuracy']
 69     )
 70     return nn
 71 
 72 def train(nn, train_image, train_label, test_image, test_label, batch_size, epoch, log_path):
 73     # Create Tensorboard callback
 74     tb = tf.keras.callbacks.TensorBoard(log_dir=log_path, histogram_freq=1)
 75     # Create learning rate reducer
 76     reduce_lr = ReduceLROnPlateau(monitor='val_loss', patience=10, mode='auto')
 77     history = nn.fit(train_image, train_label,
 78               batch_size=batch_size, epochs=epoch, validation_data=(test_image, test_label), callbacks=[tb, reduce_lr])
 79     return history
 80 
 81 
 82 if __name__ == '__main__':
 83     parser = argparse.ArgumentParser()
 84     parser.add_argument('--cpu', type=bool, default=False)
 85     parser.add_argument('--weights', type=str, default=None)
 86     args = parser.parse_args()
 87 
 88     # Force CPU or GPU
 89     os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
 90     os.environ["CUDA_VISIBLE_DEVICES"] = "-1" if args.cpu else "0"
 91     if not args.cpu:
 92         # Fix CUDNN_STATUS_INTERNAL_ERROR
 93         gpu_devices = tf.config.experimental.list_physical_devices('GPU')
 94         for device in gpu_devices:
 95             tf.config.experimental.set_memory_growth(device, True)
 96 
 97     # 1 - Load dataset
 98     digits = load_digits()
 99     X = digits['images']
100     Y = digits['target']
101 
102     # 2 - Pretreatment
103     # 2.1 - Reshape the images, from (8, 8) to (8, 8, 1)
104     X = img_reshape(X)
105     # 2.2 - Normalize the images, scale the value to 0.0 ~ 1.0
106     X = normalization(X)
107     # 2.3 - Onehot encoding on labels
108     Y = onehot_encode(Y)
109     Y = np.array(Y)
110     # 2.4 - Split the train-set and test-set
111     X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0)
112     print('Images shape: ', X.shape)
113     print('Labels shape: ', Y.shape)
114     print('Images: ', X)
115     print('Labels: ', Y)
116 
117     # 3 - Create model
118     model = CNN()
119     model.summary()
120 
121     # 4 - Training
122     if not args.weights:
123         log_dir = "./logs/fit/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
124         train(model, X_train, Y_train, X_test, Y_test, batch_size=4, epoch=80, log_path=log_dir)
125         model.save("./weights.hdf5") # Save the weights
126 
127     # 5 - Evaluate
128     # 5.1 - model.evaluate()
129     if args.weights:
130         model.load_weights(args.weights)
131     print("\nModel Evaluate:")
132     model.evaluate(X_test, Y_test, batch_size=4)
133     # 5.2 - pandas.crosstab()
134     pred = model.predict_classes(X_test)
135     table = pandas.DataFrame(pandas.crosstab(onehot_decode(Y_test), pred, rownames=['true'], colnames=['pred']))
136     heatmap(table, annot=True, cmap="Reds", linewidths=0.2, linecolor='G')
137     plt.show()

 

posted @ 2020-06-08 14:09  C137  阅读(329)  评论(0)    收藏  举报