前言
没有编程能力,代码全靠找。找了非常久的代码,难得能用的。
我的TensorFlow是2.7.0版本的,亲测代码可用。
卷积神经网络
CNN代码出处:深度学习–TensorFlow(项目)识别自己的手写数字(基于CNN卷积神经网络)
CNN训练代码
# CNN
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.datasets import mnist
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout, Convolution2D, MaxPooling2D, Flatten
from tensorflow.keras.optimizers import Adam
# 1、载入数据
(train_data, train_target), (test_data, test_target) = mnist.load_data()
# 2、改变数据维度
train_data = train_data.reshape(-1, 28, 28, 1)
test_data = test_data.reshape(-1, 28, 28, 1)
# 注:在TensorFlow中,在做卷积的时候需要把数据变成4维的格式
# 这4个维度分别是:数据数量,图片高度,图片宽度,图片通道数
# 3、归一化(有助于提升训练速度)
train_data = train_data / 255.0
test_data = test_data / 255.0
# 4、独热编码
train_target = to_categorical(train_target, num_classes=10)
test_target = to_categorical(test_target, num_classes=10) # 10种结果
# 5、搭建CNN卷积神经网络
model = Sequential()
# 5-1、第一层:卷积层+池化层
# 第一个卷积层
model.add(
Convolution2D(input_shape=(28, 28, 1), filters=32, kernel_size=5, strides=1, padding='same', activation='relu'))
# 卷积层 输入数据 滤波器数量 卷积核大小 步长 填充数据(same padding) 激活函数
# 第一个池化层 # pool_size
model.add(MaxPooling2D(pool_size=2, strides=2, padding='same', ))
# 池化层(最大池化) 池化窗口大小 步长 填充方式
# 5-2、第二层:卷积层+池化层
# 第二个卷积层
model.add(Convolution2D(64, 5, strides=1, padding='same', activation='relu'))
# 64:滤波器个数 5:卷积窗口大小
# 第二个池化层
model.add(MaxPooling2D(2, 2, 'same'))
# 5-3、扁平化 (相当于把(64,7,7,64)数据->(64,7*7*64))
model.add(Flatten())
# 5-4、第三层:第一个全连接层
model.add(Dense(1024, activation='relu'))
model.add(Dropout(0.5))
# 5-5、第四层:第二个全连接层(输出层)
model.add(Dense(10, activation='softmax'))
# 10:输出神经元个数
# 6、编译
model.compile(optimizer=Adam(learning_rate=1e-4), loss='categorical_crossentropy', metrics=['accuracy'])
# 优化器(adam) 损失函数(交叉熵损失函数) 标签
# 7、训练
model.fit(train_data, train_target, batch_size=64, epochs=10, validation_data=(test_data, test_target))
# 8、保存模型
model.save('mnist.h5')
输出:
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step
11501568/11490434 [==============================] - 0s 0us/step
Epoch 1/10
938/938 [==============================] - 24s 11ms/step - loss: 0.3301 - accuracy: 0.9055 - val_loss: 0.0860 - val_accuracy: 0.9740
Epoch 2/10
938/938 [==============================] - 10s 10ms/step - loss: 0.0922 - accuracy: 0.9725 - val_loss: 0.0519 - val_accuracy: 0.9834
Epoch 3/10
938/938 [==============================] - 10s 10ms/step - loss: 0.0646 - accuracy: 0.9800 - val_loss: 0.0390 - val_accuracy: 0.9870
Epoch 4/10
938/938 [==============================] - 10s 10ms/step - loss: 0.0515 - accuracy: 0.9839 - val_loss: 0.0337 - val_accuracy: 0.9881
Epoch 5/10
938/938 [==============================] - 10s 11ms/step - loss: 0.0428 - accuracy: 0.9875 - val_loss: 0.0327 - val_accuracy: 0.9888
Epoch 6/10
938/938 [==============================] - 10s 10ms/step - loss: 0.0368 - accuracy: 0.9891 - val_loss: 0.0255 - val_accuracy: 0.9910
Epoch 7/10
938/938 [==============================] - 10s 11ms/step - loss: 0.0309 - accuracy: 0.9903 - val_loss: 0.0251 - val_accuracy: 0.9911
Epoch 8/10
938/938 [==============================] - 10s 11ms/step - loss: 0.0269 - accuracy: 0.9914 - val_loss: 0.0217 - val_accuracy: 0.9921
Epoch 9/10
938/938 [==============================] - 10s 11ms/step - loss: 0.0241 - accuracy: 0.9926 - val_loss: 0.0223 - val_accuracy: 0.9923
Epoch 10/10
938/938 [==============================] - 10s 11ms/step - loss: 0.0206 - accuracy: 0.9936 - val_loss: 0.0208 - val_accuracy: 0.9921
CNN识别代码
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
import tensorflow as tf
from tensorflow.keras.models import load_model
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
# 1、载入数据
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 2、载入训练好的模型
model = load_model('mnist.h5')
# 3、载入自己写的数字图片并设置大小
img = Image.open('C:/Users/shiro/dl/datas/6/1869-6.bmp')
# 设置大小(和数据集的图片一致)
img = img.resize((28, 28))
# 4、转灰度图
gray = np.array(img.convert('L')) #.convert('L'):转灰度图
# 5、转黑底白字、数据归一化
gray_inv = (255-gray)/255.0
# 6、转四维数据(CNN预测需要)
image = gray_inv.reshape((1,28,28,1))
# 7、预测
prediction = model.predict(image) # 预测
prediction = np.argmax(prediction,axis=1) # 找出最大值
print('预测结果:', prediction)
# 8、显示
# 设置plt图表
f, ax = plt.subplots(2, 2, figsize=(5, 5))
# 显示数据集图像
ax[0][0].set_title('train_model')
ax[0][0].axis('off')
ax[0][0].imshow(x_train[18], 'gray')
# 显示原图
ax[0][1].set_title('img')
ax[0][1].axis('off')
ax[0][1].imshow(img, 'gray')
# 显示灰度图(白底黑字)
ax[1][0].set_title('gray')
ax[1][0].axis('off')
ax[1][0].imshow(gray, 'gray')
# 显示灰度图(黑底白字)
ax[1][1].set_title(f'predict:{prediction}')
ax[1][1].axis('off')
ax[1][1].imshow(gray_inv, 'gray')
plt.show()
预测结果:
循环神经网络
原项目地址:https://github.com/aymericdamien/TensorFlow-Examples 我这运行的时候有奇怪的Bug,遂添加了行代码。
# RNN
from __future__ import absolute_import, division, print_function
# 导入TensorFlow v2.
import tensorflow as tf
from tensorflow.keras import Model, layers
import numpy as np
tf.compat.v1.enable_eager_execution() # 自己添加的
# MNIST 数据集参数
num_classes = 10 # 所有类别(数字 0-9)
num_features = 784 # 数据特征 (图像形状: 28*28)
# 训练参数
learning_rate = 0.001
training_steps = 1000
batch_size = 32
display_step = 100
# 网络参数
# MNIST的图像形状为28 * 28px,因此我们将为每个样本处理28个时间步长的28个序列。
num_input = 28 # 序列数
timesteps = 28 # 时间步长
num_units = 32 # LSTM层神经元数目
# 准备MNIST数据
from tensorflow.keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 转化为float32
x_train, x_test = np.array(x_train, np.float32), np.array(x_test, np.float32)
# 将图像展平为784个特征的一维向量(28*28)。
x_train, x_test = x_train.reshape([-1, 28, 28]), x_test.reshape([-1, num_features])
# 将图像值从[0,255]归一化到[0,1]
x_train, x_test = x_train / 255., x_test / 255.
# 使用tf.data API对数据进行随机排序和批处理
train_data = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_data = train_data.repeat().shuffle(5000).batch(batch_size).prefetch(1)
# 创建LSTM模型
class LSTM(Model):
# 创建TF模型
def __init__(self):
super(LSTM, self).__init__()
# RNN (LSTM) 隐含层
self.lstm_layer = layers.LSTM(units=num_units)
self.out = layers.Dense(num_classes)
# 前向传播
def call(self, x, is_training=False):
# LSTM层
x = self.lstm_layer(x)
# 输出层 (num_classes).
x = self.out(x)
if not is_training:
# tf 交叉熵接收没有经过softmax的概率输出,所以只有不是训练时才应用softmax
x = tf.nn.softmax(x)
return x
# 创建LSTM模型
lstm_net = LSTM()
# 交叉熵损失
# 注意,这将对概率输出应用'softmax'
def cross_entropy_loss(x, y):
# 将标签转换为int 64 作为tf交叉熵函数的输入
y = tf.cast(y, tf.int64)
# 对概率输出应用softmax并计算交叉熵
loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=x)
# 批中的平均损失
return tf.reduce_mean(loss)
# 准确率评估
def accuracy(y_pred, y_true):
# 预测类是预测向量(即argmax)分数最高的分量下标
correct_prediction = tf.equal(tf.argmax(y_pred, 1), tf.cast(y_true, tf.int64))
return tf.reduce_mean(tf.cast(correct_prediction, tf.float32), axis=-1)
# Adam 优化器
optimizer = tf.optimizers.Adam(learning_rate)
# 优化过程
def run_optimization(x, y):
# 将计算封装在GradientTape中以实现自动微分
with tf.GradientTape() as g:
# 前向传播
pred = lstm_net(x, is_training=True)
# 计算损失
loss = cross_entropy_loss(pred, y)
# 要更新的变量,即可训练变量
trainable_variables = lstm_net.trainable_variables
# 计算梯度
gradients = g.gradient(loss, trainable_variables)
# 按gradients更新 W 和 b
optimizer.apply_gradients(zip(gradients, trainable_variables))
# 针对给定步骤数进行训练
for step, (batch_x, batch_y) in enumerate(train_data.take(training_steps), 1):
# 运行优化过程以更新W和b值
run_optimization(batch_x, batch_y)
if step % display_step == 0:
pred = lstm_net(batch_x, is_training=True)
loss = cross_entropy_loss(pred, batch_y)
acc = accuracy(pred, batch_y)
print("step: %i, loss: %f, accuracy: %f" % (step, loss, acc))
朴素贝叶斯分类
代码出处:统计学习方法与Python实现(三)——朴素贝叶斯法 在原版的基础上修改了引入数据集的位置,改为keras中的mnist数据集。
# 朴素贝叶斯
from tensorflow.keras.datasets import mnist
import numpy as np
(train_data, train_label), (test_data, test_label) = mnist.load_data()
# 训练集和测试集大小
train_length = 60000
test_length = 10000
size = 28 * 28 # 输入特征向量长度
data_kind = 10 # 分为几类
choice = 2 # 每个向量有几种取值
lam = 1 # 贝叶斯估计中的lamda
# 预处理数据
train_data = train_data[:train_length].reshape(train_length, size)
# 数据二值化
np.place(train_data, train_data > 0, 1)
train_label = np.array(train_label, dtype='int8')
train_label = train_label[:train_length].reshape(train_length, )
test_data = test_data[:test_length].reshape(test_length, size)
np.place(test_data, test_data > 0, 1) # 数据二值化
test_label = np.array(test_label, dtype='int8')
test_label = test_label[:test_length].reshape(test_length, )
# 初始化数组记录条件概率和先验概率
P_con = np.zeros([data_kind, size, choice])
P_pre = np.zeros(data_kind)
# 计算先验概率
def compute_P_pre(label, P_init, lamda=1):
pre = P_init
for la in label:
pre[int(la)] += 1
pre += lamda
return pre / (label.shape[0] + pre.shape[0] * lamda)
# 计算条件概率
def compute_P_con(data, label, P_init, lamda=1):
con = P_init
summ = np.zeros(P_init.shape[0])
for index, value in enumerate(data):
for jndex, dalue in enumerate(value):
con[int(label[index]), jndex, int(dalue)] += 1
summ[int(label[index])] += 1
con += lamda
summ += lamda * 2
for index, value in enumerate(con):
con[index] /= summ[index]
return con
# 进行测试
def Bayes_divide(pre, con, test, label):
acc = 0
ans = np.full(test.shape[0], -1)
P_div = np.ones([test.shape[0], pre.shape[0]])
for index, value in enumerate(test):
for times in range(pre.shape[0]):
for jndex, dalue in enumerate(value):
P_div[index, times] *= con[times, jndex, int(dalue)]
P_div[index, times] *= pre[times]
for index, temp in enumerate(P_div):
ans[index] = temp.argmax()
if ans[index] == label[index]:
acc += 1
return acc / label.shape[0], ans
P_pre = compute_P_pre(train_label, P_pre, lamda=lam)
P_con = compute_P_con(train_data, train_label, P_con, lamda=lam)
acc, ans = Bayes_divide(P_pre, P_con, test_data, test_label)
print('acc', acc)
# 最后的生成模型代码我没有添加
输出:
acc 0.8413