实验三 神经网络及Python实现实验
- 实验目的和要求
- 掌握全连接神经网络的基本原理。
- 掌握卷积神经网络的基本原理。
- 学会使用Python,Keras实现全连接神经网络。
- 学会使用Python,Keras实现卷积神经网络。
- 实验原理及内容
- 使用全连接神经网络对进行回归分析,预测汽车燃油效率(每加仑燃油公里数);需要对缺失值进行处理。从数据集中抽出后10%作为测试数据集。
- 使用Keras搭建神经网络;
- 使用matplotlib画出在训练过程中每个epoch对应的训练误差和测试误差;
- 对Keras神经网络进行优化训练,并计算测试数据的指标r2和mse。
数据说明如下:
- 每加仑燃油公里数(目标值)
- 气缸数
- 排量
- 马力
- 重量
- 加速
- 模型年份
- 原型(类别特征)
- 车型(可不使用)
18.0 8 307.0 130.0 3504. 12.0 70 1 "chevrolet chevelle malibu"
15.0 8 350.0 165.0 3693. 11.5 70 1 "buick skylark 320"
18.0 8 318.0 150.0 3436. 11.0 70 1 "plymouth satellite"
第七章内容的书上的代码得自己敲的,给的链接里并没有后几张的代码,所以让我们先成功地将书上的代码运行后再进行编写。首先先确认好环境的配置,用清华源把你的scikit-learn,tensorflow和pandas装好。可以用pip show来看你是否装好,确保你装的不是空的。
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install tensorflow -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install scikit-learn -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pandas -i Simple Index
下载完成后使用pip show 检验
例:
好了准备完成,然我们跟着书上敲一遍,完成第一遍尝试吧!
import tensorflow as tf
from keras.datasets import mnist
from keras import models
from keras import layers
import numpy as np
from sklearn.preprocessing import OneHotEncoder
import matplotlib.pyplot as plt
(train_data, train_labels), (test_data, test_labels) = mnist.load_data()
train_data = train_data.reshape((60000, 28 * 28)) # 训练特征转换为一维向量
test_data.astype("float32") / 255 # 归一化,防止数值差值太大
test_data = test_data.reshape((10000, 28 * 28)) # 训练特征转换为一维向量
test_data.astype("float32") / 255 # 归一化,防止数值差值太大
train_labels = train_labels.reshape(60000, 1)
test_labels = test_labels.reshape(10000, 1) # 标签转换为一维向量
onehot_encoder = OneHotEncoder(sparse=False) # 设置独热编码格式
train_labels = onehot_encoder.fit_transform(train_labels) # 得到编码结果
train_labels = tf.squeeze(train_labels) # 删除编码后维度为1的样本标签
test_labels = onehot_encoder.fit_transform(test_labels)
test_labels = tf.squeeze(test_labels)
neural_net = models.Sequential() # 组合层级叠加的网络架构
neural_net.add(
layers.Dense(units=512, activation="relu", input_shape=(28 * 28,))
) # 设置隐含层的神经元数量和激活函数
neural_net.add(layers.Dense(units=10, activation="softmax"))
# 设置输出层神经元数量和激活函数
neural_net.summary() # 输出网络初始化的各参数状况
neural_net.compile( # 配置网络的训练方法
optimizer=tf.keras.optimizers.SGD(learning_rate=0.1),
# 设置优化算法为梯度下降,学习率为0.1
loss="mse", # 设置损失函数为均方误差
metrics=["accuracy"], # 设置变量accuracy用于存储分类准确率
)
history = neural_net.fit(train_data, train_labels, epochs=50, batch_size=512)
# 执行模型的训练
epochs_list = list(range(0, 50)) # 训练次数
loss_list = history.history["loss"] # 训练的损失值
accuracy_list = history.history["accuracy"] # 训练的准确率
pre_result = neural_net.predict(test_data) # 对测试集预测结果
pre_result = np.argmax(pre_result, axis=1) # 获取图片类别
plt.plot(epochs_list, loss_list, label="loss")
# 以轮次为x轴,损失值为y轴绘制曲线
plt.ylabel("loss") # Y轴名字
plt.xlabel("epoch") # X轴名字
plt.legend(["loss"], loc="upper left") # 设置图例及其位置
plt.show()
plt.plot(epochs_list, accuracy_list, label="accuracy")
plt.ylabel("accuracy")
plt.xlabel("epoch")
plt.legend(["loss"], loc="upper left") # 设置图例及其位置
plt.show()
test_loss, test_acc = neural_net.evaluate(test_data, test_labels)
# 测试后的模型
print(test_loss, test_acc)
运行结果如下:
呃呃,看得出来,我们的neruo sama的成绩似乎并不是很理想,但是没有关系,跑出来就算成功!那我们赶紧熟练地使用ctrl C +Ctrl V完成这道题目吧!
当然,因为这道题数据的复杂性,所以我们这直接运用pandas进行读取完成,并在简单的分析后发现这其实是依旧是一道线性回归问题,用神经网络去预测第一列的数据,那么第一列作为标签其余数据作为特征去进行训练即可。
这里读取主要用pandas,因为loadtxt获取后面的字符串还好,主要是这些数据间的分割有的是制表符有的是个数不同的空格,还有缺省值?号的存在,经常报错很难去调整好,所以我们用pandas读取非常便捷。
首先是获取数据,并将缺省值进行替换。
# 读取文本文件
df = pd.read_csv(
r"E:\progress\B21030826\python\Automotive_fuel_efficiency.txt",
sep="\s+",
header=None,
na_values=["?"],
)
# 删除所有包含 NaN 值的行
df = df.dropna()
# 只保留最后一列字符串数据,并将其他数据读入
data = df.iloc[:, :-1].values
# 获取最后一列字符串数据
strings = df.iloc[:, -1].values
# 将数据划分为特征和标签
X = data[:, 1:] # 特征
Y = data[:, 0] # 标签
第二步就是堆数据进行处理后划分,将连续特征归一,类型特征编码。
# 对第8列进行独热编码
encod = OneHotEncoder(sparse=False, categories="auto", handle_unknown="ignore")
# OneHotEncoder函数的handle_unknown参数指定了对未知类别的处理方式,
# 默认为'error'(抛出错误),如果原数据中含有未知类别,则会导致编码失败,
# 因此需要将其设置为'ignore'。
prototypes = [[row[7]] for row in data]
prototypes_encoded = encod.fit_transform(prototypes)
# 将编码结果插入到特征矩阵中
X_encoded = np.insert(X, -1, prototypes_encoded.T, axis=1)
# 归一化前7列特征
scaler = MinMaxScaler()
X = scaler.fit_transform(X[:, :7])
# 将数据划分为训练集和10%测试集,随机种子固定好重复实验
train_data, test_data, train_labels, test_labels = train_test_split(
X, Y, test_size=0.1, random_state=10
)
然后是神经网络的创建并配置对应的学习方法
neural_net = models.Sequential()
# 输入层到第1个隐藏层
neural_net.add(layers.Dense(units=512, activation="relu", input_dim=7))
neural_net.add(
layers.Dense(units=1, activation="linear")
) # 输出层,输出1个即可,不使用softmax获取概率,因为是回归问题
print(neural_net.summary()) # 输出网络初始化的各参数状况
# 配置网络的训练方法
neural_net.compile(
# 设置优化算法为梯度下降,学习率为0.1
optimizer=tf.keras.optimizers.SGD(learning_rate=0.01),
loss="mse", # 设置损失函数为均方误差
metrics=["accuracy"], # 设置变量accuracy用于存储分类准确率
)
最后是模型的训练和输出
history = neural_net.fit(
train_data,
train_labels,
epochs=50,
batch_size=128,
validation_data=(test_data, test_labels),
) # 执行模型的训练
epochs_list = list(range(0, 64)) # 训练次数
train_loss_list = history.history["loss"] # 训练的损失值
test_loss_list = history.history["val_loss"] # 测试集上的损失值
accuracy_list = history.history["accuracy"] # 训练的准确率
pre_result = neural_net.predict(test_data) # 对测试集预测结果
test_loss, test_acc = neural_net.evaluate(test_data, test_labels) # 测试后的模型
plt.plot(epochs_list, train_loss_list, label="Train Loss")
plt.plot(epochs_list, test_loss_list, label="Test Loss")
plt.ylabel("loss") # Y轴名字
plt.xlabel("epoch") # X轴名字
plt.legend(loc="upper left") # 设置图例及其位置
plt.show()
print("test_loss: ", test_loss, "test_acc: ", test_acc)
r2 = r2_score(test_labels, pre_result)
mse = mean_squared_error(test_labels, pre_result)
print("r2:", r2, "mse:", mse)
然后将最终结果输出,以下为效果图
0.7几神中神,足够了
但我们简单的优化一下,不如增加训练次数降低神经元数量
neural_net.add(layers.Dense(units=128, activation="relu", input_dim=7)) history = neural_net.fit( train_data, train_labels, epochs=64, batch_size=128, validation_data=(test_data, test_labels), ) # 执行模型的训练 epochs_list = list(range(0, 64)) # 训练次数
效果如图:
给出整体代码:
import numpy as np
import tensorflow as tf
from keras import models
from keras import layers
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, mean_squared_error
import matplotlib.pyplot as plt
import pandas as pd
# 读取文本文件
df = pd.read_csv(
r"E:\progress\B21030826\python\Automotive_fuel_efficiency.txt",
sep="\s+",
header=None,
na_values=["?"],
)
# 删除所有包含 NaN 值的行
df = df.dropna()
# 只保留最后一列字符串数据,并将其他数据读入
data = df.iloc[:, :-1].values
# 获取最后一列字符串数据
strings = df.iloc[:, -1].values
# 将数据划分为特征和标签
X = data[:, 1:] # 特征
Y = data[:, 0] # 标签
# 对第8列进行独热编码
encod = OneHotEncoder(sparse=False, categories="auto", handle_unknown="ignore")
# OneHotEncoder函数的handle_unknown参数指定了对未知类别的处理方式,
# 默认为'error'(抛出错误),如果原数据中含有未知类别,则会导致编码失败,
# 因此需要将其设置为'ignore'。
prototypes = [[row[7]] for row in data]
prototypes_encoded = encod.fit_transform(prototypes)
# 将编码结果插入到特征矩阵中
X_encoded = np.insert(X, -1, prototypes_encoded.T, axis=1)
# 归一化前7列特征
scaler = MinMaxScaler()
X = scaler.fit_transform(X[:, :7])
# 将数据划分为训练集和10%测试集,随机种子固定好重复实验
train_data, test_data, train_labels, test_labels = train_test_split(
X, Y, test_size=0.1, random_state=10
)
neural_net = models.Sequential()
# 输入层到第1个隐藏层
neural_net.add(layers.Dense(units=128, activation="relu", input_dim=7))
neural_net.add(
layers.Dense(units=1, activation="linear")
) # 输出层,输出1个即可,不使用softmax获取概率,因为是回归问题
print(neural_net.summary()) # 输出网络初始化的各参数状况
# 配置网络的训练方法
neural_net.compile(
# 设置优化算法为梯度下降,学习率为0.1
optimizer=tf.keras.optimizers.SGD(learning_rate=0.01),
loss="mse", # 设置损失函数为均方误差
metrics=["accuracy"], # 设置变量accuracy用于存储分类准确率
)
history = neural_net.fit(
train_data,
train_labels,
epochs=64,
batch_size=128,
validation_data=(test_data, test_labels),
) # 执行模型的训练
epochs_list = list(range(0, 64)) # 训练次数
train_loss_list = history.history["loss"] # 训练的损失值
test_loss_list = history.history["val_loss"] # 测试集上的损失值
accuracy_list = history.history["accuracy"] # 训练的准确率
pre_result = neural_net.predict(test_data) # 对测试集预测结果
test_loss, test_acc = neural_net.evaluate(test_data, test_labels) # 测试后的模型
plt.plot(epochs_list, train_loss_list, label="Train Loss")
plt.plot(epochs_list, test_loss_list, label="Test Loss")
plt.ylabel("loss") # Y轴名字
plt.xlabel("epoch") # X轴名字
plt.legend(loc="upper left") # 设置图例及其位置
plt.show()
print("test_loss: ", test_loss, "test_acc: ", test_acc)
r2 = r2_score(test_labels, pre_result)
mse = mean_squared_error(test_labels, pre_result)
print("r2:", r2, "mse:", mse)
但其实还比较好奇那个自定义代码效果,试着敲完编一下。
我无话可说,书上好像也没给出evaluate的写法,去看keras的源代码model类里evaluate函数打算自己写一个,写着半截,才看到了test可以计算函数,彳亍,这就是没有熟读代码的后果,书上的小错误,让我们直接来看结果。
很明显这次是真的慢多了,跑了得有两三分钟,不过准确率确实高啊,这才叫优化啊,那么我们先给出书上的自定义代码,若有兴趣可以试着优化一下该题的自定义代码。
书上代码:
import tensorflow as tf
from keras.datasets import mnist
import numpy as np
from tqdm import trange
def Load_data():
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape((60000, 28 * 28)) # 训练特征转换为一维向量
x_test = x_test.reshape((x_test.shape[0], 28 * 28)) # 测试集
x_train.astype("float32") # 转换格式
x_test.astype("float32") #
x_train, x_test = x_train / 255, x_test / 255
y_train = tf.keras.utils.to_categorical(y_train) # 对标签进行编码
y_test = tf.keras.utils.to_categorical(y_test)
return (x_train, y_train), (x_test, y_test)
# 全连接神经网络
class FullConectionLayer:
def __init__(self):
self.mem = {}
def forward(self, X, W):
self.mem["X"] = X # 接收输入数据
self.mem["W"] = W # 接受网络参数,W网络连接权重矩阵
H = np.matmul(X, W) # 网络输出
return H
def backward(self, grad_H):
X = self.mem["X"] # 获取成员变量
W = self.mem["W"]
grad_X = np.matmul(grad_H, W.T)
grad_W = np.matmul(X.T, grad_H)
return grad_X, grad_W
# 激活函数和损失函数
class ReLU:
def __init__(self):
self.mem = {}
def forward(self, X):
self.mem["X"] = X # 接收输入数据
return np.where(X > 0, X, np.zeros_like(X)) # 非正数替换成0
def backward(self, grad_y):
X = self.mem["X"]
return (X > 0).astype(np.float32) * grad_y # 对RELU求导
# 交叉熵损失函数
class CrossEntropy:
def __init__(self):
self.mem = {}
self.epsilon = 1e-12 # 防止求导后分母为0
def forward(self, p, y):
self.mem["p"] = p # 接收输入数据
log_p = np.log(p + self.epsilon)
return np.mean(np.sum(-y * log_p, axis=1)) # 计算损失值
def backward(self, y): # 计算梯度
p = self.mem["p"]
return -y * (1 / (p + self.epsilon)) # 计算损失函数关于p的梯度
class SoftMax:
def __init__(self):
self.mem = {}
self.epsilon = 1e-12 # 防止求导后分母为0
def forward(self, p):
p_exp = np.exp(p)
denominator = np.sum(p_exp, axis=1, keepdims=True)
s = p_exp / (denominator + self.epsilon) # softmax的表达式
self.mem["s"] = s # 接收输入数据
self.mem["p_exp"] = p_exp # 接收输入数据
return s
def backward(self, grad_s): # 计算grad_s的梯度
s = self.mem["s"]
siji = np.matmul(np.expand_dims(s, axis=2), np.expand_dims(s, axis=1))
tmp = np.matmul(np.expand_dims(grad_s, axis=1), siji) # 矩阵相乘
tmp = np.squeeze(tmp, axis=1) # 去掉shape为1的维度
grad_p = -tmp + grad_s * s
return grad_p
# 全连接神经网络模型
class FullConectionModel:
def __init__(self, latent_dims):
self.W1 = np.random.normal(
loc=0, scale=1, size=[28 * 28 + 1, latent_dims]
) / np.sqrt((28 * 28 + 1) / 2)
self.W2 = np.random.normal(loc=0, scale=1, size=[latent_dims, 10]) / np.sqrt(
latent_dims / 2
)
self.mul_h1 = FullConectionLayer() # 隐含层
self.relu = ReLU() # 激活函数
self.mul_h2 = FullConectionLayer() # 输出层
self.softmax = SoftMax() # 激活函数
self.cross_en = CrossEntropy() # 损失函数
def forward(self, X, labels):
bias = np.ones(shape=[X.shape[0], 1]) # 生成权值均为1的矩阵作为偏置
X = np.concatenate([X, bias], axis=1)
self.h1 = self.mul_h1.forward(X, self.W1) # 隐含层计算
self.h1_relu = self.relu.forward(self.h1) # 隐含层激活函数处理
self.h2 = self.mul_h2.forward(self.h1_relu, self.W2) # 输出层计算
self.h2_soft = self.softmax.forward(self.h2) # 输出层激活函数处理
self.loss = self.cross_en.forward(self.h2_soft, labels) # 计算交叉熵损失函数
def backward(self, labels):
self.loss_grad = self.cross_en.backward(labels) # 计算损失函数在输出层的梯度
self.h2_soft_grad = self.softmax.backward(self.loss_grad) # 求导
# 求导
self.h2_grad, self.W2_grad = self.mul_h2.backward(self.h2_soft_grad)
self.h1_relu_grad = self.relu.backward(self.h2_grad) # 求导
# 计算隐含层的梯度
self.h1_grad, self.W1_grad = self.mul_h1.backward(self.h1_relu_grad)
# 准确率函数
def computeAccuracy(prob, labels):
# prob 预测值,labels真实值
predictions = np.argmax(prob, axis=1) # 分类结果
truth = np.argmax(labels, axis=1) # 获取真实值
return np.mean(predictions == truth)
# 训练函数
def trainOneStep(model, x_train, y_train, learning_rate=1e-5):
# 首先定义单步训练函数
model.forward(x_train, y_train) # 前向传播
model.backward(y_train) # 反向传播
model.W1 += -learning_rate * model.W1_grad # 更新参数
model.W2 += -learning_rate * model.W2_grad # 更新参数
loss = model.loss # 损失函数值
accuracy = computeAccuracy(model.h2_soft, y_train) # 计算准确率
return loss, accuracy
def train(x_train, y_train, x_validation, y_validation): # 定义训练函数
epochs = 50 # 训练批次的样本量
learning_rate = 1e-5 # 学习率
latent_dims_list = [100, 200, 300] # 参数列表
best_accuracy = 0 # 存储最佳的准确率
best_latent_dims = 0 # 存储最新的参数
print("Start seaching the best parameter..n") # 在验证集上寻优
for latent_dims in latent_dims_list: # 遍历参数列表
model = FullConectionModel(latent_dims) # 在该参数 下运行模型
bar = trange(20) # 使用tqdm第三方库,调用tqdm.std.range方法实现以
# 进度条的显示进度
for epoch in bar: # 训练
loss, accuracy = trainOneStep(model, x_train, y_train, learning_rate)
# 训练并获损失和准确率
bar.set_description(
f"Parameter latent dims= {latent_dims: <3},epoch = {epoch + 1: <3},loss = {loss<10.8},"
f"accuracy= {accuracy:<8.6}"
) # 给进度条加个描述
bar.close() # 关闭进度条
validation_loss, validation_accuracy = test(model, x_validation, y_validation)
# 运行在验证集
print(
f"Parameter latent_dims= {latent_dims: <3}, validation_loss= {validation_loss},validation_accuracy={ validation_accuracy}.\n"
) # 显示验证结果
if validation_accuracy > best_accuracy: # 判断最佳准确率
best_accuracy = validation_accuracy # 获取最高的准确率
best_latent_dims = latent_dims # 获取参数列表中各参数对应的准确率
print(f"The best parameter is {best_latent_dims}.\n") # 选择最高准确率对应的参数
print("Start training the best model..") # 开始训练模型
best_model = FullConectionModel(best_latent_dims) # 执行模型
x = np.concatenate([x_train, x_validation], axis=0) # 将训练集与验证集合并
y = np.concatenate([y_train, y_validation], axis=0) # 将训练集与验证集合并
bar = trange(epochs) # 显示进度条
for epoch in bar: # 开启训练循环
loss, accuracy = trainOneStep(best_model, x, y, learning_rate) # 训练模型
bar.set_description(
f"Trining; the best model, epoch={epoch+1: <3}, loss={loss: <10.8},accuracy= {accuracy: <8.6}"
) # 给进度条加个描述
bar.close() # 关闭进度条
return best_model # 返回训|练后的模型
# 测试函数
def test(model, x, y):
model.forward(x, y)
loss = model.loss
accuracy = computeAccuracy(model.h2_soft, y)
return loss, accuracy
if __name__ == "__main__":
(train_data, train_labels), (test_data, test_labels) = Load_data()
valid_data, valid_labels = train_data[:5000], train_labels[:5000]
train_data, train_labels = train_data[5000:], train_labels[5000:]
model = train(train_data, train_labels, valid_data, valid_labels)
loss, accuracy = test(model, test_data, test_labels)
print(f"Evaluate the best model,test loss={loss:0<10.8},accuracy={accuracy:0<8.6}.")
2、参考最新版第八章“8.6 卷积神经网络及Python实现”内容,完成以下实验。
- 参考书上代码,下载MNIST数据,使用Keras/Tensorflow实现基础卷积神经网络对其进行训练和测试预测;
- 试着改变卷积神经网络的层数为10层以上,根据自己的想法设置各层,看能否提升分类效果;
惯例,先把书上的图跑一遍,明显跑起来是比全连接神经慢的,花了1min多吧
嗯,82934,没毛病
可以,数据还是挺漂亮的
98.8%的正确率,着实恐怖,我们的目标就是超过他。
先给出书上代码
import numpy as np
import matplotlib.pylab as plt
from keras import Sequential
from keras.datasets import mnist
from keras.layers import Conv2D, MaxPooling2D, Dense, Dropout, Flatten
def normorlize(x):
x = x.astype(np.float32) / 255.0
return x
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1).astype("float32")
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1).astype("float32")
x_train = normorlize(x_train)
x_test = normorlize(x_test)
model = Sequential()
model.add(Conv2D(filters=8, kernel_size=(5, 5), padding='same', input_shape=(28, 28, 1), activation='relu')) # 第一层卷积层
model.add(MaxPooling2D(pool_size=(2, 2), padding='same')) # 第一个池化层
model.add(Conv2D(filters=16, kernel_size=(5, 5), padding='same', activation='relu')) # 第二层卷积层
model.add(MaxPooling2D(pool_size=(2, 2), padding='same')) # 第二个池化层
model.add(Flatten()) # 将特征图展开为一维
model.add(Dense(256, activation='relu')) # 全连接层的隐含层
model.add(Dropout(0.5)) # Dropout防止过拟合
model.add(Dense(10, activation='softmax')) # 全连接层的输出层
print(model.summary())
model.compile(
loss="sparse_categorical_crossentropy", optimizer="adam", metrics=["accuracy"]
)
history = model.fit(
x=x_train, y=y_train, validation_split=0.2, epochs=4, batch_size=250, verbose=1
)
# 执行模型的训练
loss_list = history.history["loss"] # 训练的损失值
val_loss = history.history["val_loss"] # 训练的损失值
acc_list = history.history["accuracy"] # 训练的准确率
val_acc = history.history["val_accuracy"]
plt.plot(acc_list, label="Accuracy")
plt.plot(val_acc, label="Validation Accuracy") # 绘制这两个数据的变化图
# 以轮次为x轴,损失值为y轴绘制曲线
plt.ylabel("Accuracy") # Y轴名字
plt.xlabel("Epoch") # X轴名字
plt.ylim([0.75, 1]) # 坐标轴范围
plt.legend(loc="lower right") # 设置图例及其位置
plt.show()
plt.plot(loss_list, label="Loss")
plt.plot(val_loss, label="Validation Loss") # 绘制这两个数据的变化图
# 以轮次为x轴,损失值为y轴绘制曲线
plt.ylabel("Loss") # Y轴名字
plt.xlabel("Epoch") # X轴名字
plt.ylim([0, 0.6]) # 坐标轴范围
plt.legend(loc="upper right") # 设置图例及其位置
plt.show()
test_loss, test_acc = model.evaluate(x_test, y_test)
# 测试后的模型
print("loss: ", test_loss, "acc: ", test_acc)
随便改改,12层网络,轻松搞定。
import numpy as np
import matplotlib.pylab as plt
from keras import Sequential
from keras.datasets import mnist
from keras.layers import Conv2D, MaxPooling2D, Dense, Dropout, Flatten
def normorlize(x):
x = x.astype(np.float32) / 255.0
return x
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1).astype("float32")
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1).astype("float32")
x_train = normorlize(x_train)
x_test = normorlize(x_test)
model = Sequential()
model.add(Conv2D(filters=8, kernel_size=(5, 5), padding='same', input_shape=(28, 28, 1), activation='relu')) # 第一层卷积层
model.add(Conv2D(filters=8, kernel_size=(9, 9), padding='same', activation='relu')) # 第二层卷积层
model.add(MaxPooling2D(pool_size=(1, 1), padding='same')) # 第一个池化层
model.add(Conv2D(filters=16, kernel_size=(3, 3), padding='same', activation='relu')) # 第三层卷积层
model.add(Conv2D(filters=16, kernel_size=(3, 3), padding='same', activation='relu')) # 第四层卷积层
model.add(MaxPooling2D(pool_size=(2, 2), padding='same')) # 第二个池化层
model.add(Conv2D(filters=32, kernel_size=(5, 5), padding='same', activation='relu')) # 第五层卷积层
model.add(Conv2D(filters=32, kernel_size=(5, 5), padding='same', activation='relu')) # 第六层卷积层
model.add(MaxPooling2D(pool_size=(2, 2), padding='same')) # 第三个池化层
model.add(Conv2D(filters=16, kernel_size=(3, 3), padding='same', activation='relu')) # 第七层卷积层
model.add(MaxPooling2D(pool_size=(1, 1), padding='same')) # 第四个池化层
model.add(Flatten()) # 将特征图展开为一维
model.add(Dense(256, activation='relu')) # 全连接层的隐含层
model.add(Dropout(0.5)) # Dropout防止过拟合
model.add(Dense(10, activation='softmax')) # 全连接层的输出层
print(model.summary())
model.compile(
loss="sparse_categorical_crossentropy", optimizer="adam", metrics=["accuracy"]
)
history = model.fit(
x=x_train, y=y_train, validation_split=0.2, epochs=4, batch_size=250, verbose=1
)
# 执行模型的训练
loss_list = history.history["loss"] # 训练的损失值
val_loss = history.history["val_loss"] # 训练的损失值
acc_list = history.history["accuracy"] # 训练的准确率
val_acc = history.history["val_accuracy"]
plt.plot(acc_list, label="Accuracy")
plt.plot(val_acc, label="Validation Accuracy") # 绘制这两个数据的变化图
# 以轮次为x轴,损失值为y轴绘制曲线
plt.ylabel("Accuracy") # Y轴名字
plt.xlabel("Epoch") # X轴名字
plt.ylim([0.75, 1]) # 坐标轴范围
plt.legend(loc="lower right") # 设置图例及其位置
plt.show()
plt.plot(loss_list, label="Loss")
plt.plot(val_loss, label="Validation Loss") # 绘制这两个数据的变化图
# 以轮次为x轴,损失值为y轴绘制曲线
plt.ylabel("Loss") # Y轴名字
plt.xlabel("Epoch") # X轴名字
plt.ylim([0, 0.6]) # 坐标轴范围
plt.legend(loc="upper right") # 设置图例及其位置
plt.show()
test_loss, test_acc = model.evaluate(x_test, y_test)
# 测试后的模型
print("loss: ", test_loss, "acc: ", test_acc)