活动地址:CSDN21天学习挑战赛
我的环境
语言环境:python 3.7
编译器:pycharm + jupyter notebook
深度学习环境: tensorflow2
import tensorflow as tf
gpus = tf.config.list_physical_devices("GPU")
if gpus:
gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
tf.config.set_visible_devices([gpu0],"GPU")
import tensorflow as tf
from tensorflow.keras import datasets, layers, models
import matplotlib.pyplot as plt
(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()
# 数据存放在 C:\Users\用户名\.keras\datasets
# 或者指定路径存放
# path = r"E:\practice\tf2\mnist.npz" # 修改为数据实际路径
# (train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data(path)
数据集简介:
Mnist数据集分为两部分,分别含有60000张训练图片和10000张测试图片。
图像是28像素 * 28像素,Mnist数据集把代表一张图片的二维数据转开成一个向量,长度为28*28=784。因此在Mnist的训练数据集中mnist.train.images是一个形状为[60000, 784]的张量,第一个维度数字用来索引图片,第二个维度数字用来索引每张图片中的像素点,图片里的某个像素的强度值介于0-1之间。
Mnist数据集中的标签是介于0~9的数字,Mnist中的标签是用独热编码(one-hot-vectors)表示的,一个one-hot向量除了某一位数字是1以外,其余维度的数组都是0,比如标签0用独热编码表示为([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]),标签3用独热编码表示为([0, 0, 0, 1, 0, 0, 0, 0, 0, 0])。所以,Mnist数据集中所有的标签mnist.train.labels是一个[60000, 10]的数字矩阵。
# 将像素的值标准化至0到1的区间内。
train_images, test_images = train_images / 255.0, test_images / 255.0
train_images.shape,test_images.shape,train_labels.shape,test_labels.shape
"""
输出:((60000, 28, 28), (10000, 28, 28), (60000,), (10000,))
"""
归一化的意义:
经过标准化处理后,原始数据转化为无量纲化指标测评值,各指标值处于同一数量级别,可进行综合测评分析。
如果直接用原始指标值进行分析,就会突出数值较高的指标在综合分析中的作用,相对削弱数值水平较低指标的作用。
避免数值问题:太大的数会引发数值问题。
平衡各特征的贡献
归一化的方法:
x = (x - min)/(max - min)
通过对数据的每一个维度的值进行重新调节,使得最终的数据向量落在 [0,1]区间内。
对于图片来说,由于max是255,min是0,也就是直接除以255就可以完成归一化。
代码实现:
# 将像素的值标准化至0到1的区间内。
train_images, test_images = train_images / 255.0, test_images / 255.0
x =(x - u)/σ
u是均值 σ是标准差
将数据变换成均值为0,标准差为1的分布(但不一定为正态)。
代码实现:
transforms.Normalize(mean = (0.485, 0.456, 0.406), std = (0.229, 0.224, 0.225))
plt.figure(figsize=(20,10))
for i in range(20):
plt.subplot(5,10,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(train_images[i], cmap=plt.cm.binary)
plt.xlabel(train_labels[i])
plt.show()
#调整数据到我们需要的格式
train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))
train_images.shape,test_images.shape,train_labels.shape,test_labels.shape
"""
输出:((60000, 28, 28, 1), (10000, 28, 28, 1), (60000,), (10000,))
"""
调整数据格式的标准:查看所需模型介绍,查看输入数据的结构即可
model = models.Sequential([
layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)),#卷积层1,卷积核3*3
layers.MaxPooling2D((2, 2)), #池化层1,2*2采样
layers.Conv2D(64, (3, 3), activation='relu'), #卷积层2,卷积核3*3
layers.MaxPooling2D((2, 2)), #池化层2,2*2采样
layers.Flatten(), #Flatten层,连接卷积层与全连接层
layers.Dense(64, activation='relu'), #全连接层,特征进一步提取
layers.Dense(10) #输出层,输出预期结果
])
# 打印网络结构
model.summary()
conv2d 表示卷积层
MaxPooling2D 表示池化层
dense 表示全连接层
Param 表示每个层数的个数
Param的计算方法如下:
所以:
第一个CONV层,Conv2D(32, kernel_size=(3, 3), input_shape=(28,28,1)),Param=(3 * 3 * 1+1)*32 = 320
第二个CONV层,Conv2D(64, (3, 3), activation=‘relu’),经过第一个层32个卷积核的作用,第二层输入数据通道数为32,Param=(3 * 3 * 32+1)64 = 18496.
dense:因为flatten的作用,输出变成了1600,Dense中有64个卷积核,所以Param=64(1600+1)= 102464
"""
这里设置优化器、损失函数以及metrics
"""
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
"""
这里设置输入训练数据集(图片及标签)、验证数据集(图片及标签)以及迭代次数epochs
"""
history = model.fit(train_images, train_labels, epochs=10,
validation_data=(test_images, test_labels))
plt.imshow(test_images[1])
pre = model.predict(test_images) # 对所有测试图片进行预测
pre[1] # 输出第一张图片的预测结果
pre = model.predict(test_images)
pre.argmax(1) # 利用argmax函数直接调出预测值