深度学习-加载MNIST数据集

'''import numpy as np
# 1.采样数据
data = []                              # 保存样本集的列表
for i in range(100):                   # 循环采样100个点
    x = np.random.uniform(-10.,10.)    # 随机采样输入x
    # 采样高斯噪声
    eps = np.random.normal(0.,0.01)
    # 得到模型输出
    y = 1.477*x + 0.089 + eps
    data.append([x,y])                 # 保存样本点
data = np.array(data)                  # 转换为2DNumpy数组
# 2.计算误差
def mse(b, w, points):
    # 根据当前的w,b参数计算均方差损失
    totalError = 0
    for i in range(0,len(points)):     # 环所有迭代点
        x = points[i, 0]               # 得i号点的输入x
        y = points[i, 1]               # 得i号点的输出y
        #计算差的平方,并累加
        totalError += (y - (w*x + b)) ** 2
    # 将累加的误差求平均,得到均方差
    return totalError/float(len(points))
# 3.计算梯度
def step_grdient(b_current, w_current, points, lr):
    # 计算误差函数所在点上的导数,并更新w,b
    b_gradient = 0
    w_gradient = 0
    M = float(len(points))             # 总样本数
    for i in range(0, len(points)):
        x = points[i, 0]
        y = points[i, 1]
        # 误差函数对b的导数:grad_b = 2(wx+b-y),参考式(2.3)
        b_gradient += (2/M)*((w_current* x + b_current)-y)
        # 误差函数对w的导数:grad_b = 2(wx+b-y)* x,参考式(2.2)
        w_gradient += (2/M)*x*((w_current *x + b_current) - y)
    # 根据梯度下降算法更新w',b',其中lr为学习率
    new_b = b_current - (lr * b_gradient)
    new_w = w_current - (lr * w_gradient)
    return[new_b, new_w]
# 4.梯度更新
def gradient_descent(points, starting_b, starting_w, lr, num_iterations):
    # 循环更新w,b多次
    b = starting_b                    # b的初始值
    w = starting_w                    # w的初始值
    # 根据梯度下降算法更新多次
    for step in range(num_iterations):
        # 计算梯度并更新一次
        [b,w] = step_gradient(b,w, np.array(points),lr)
        loss = mse(b,w,points)        # 计算当前的均方差,用于监控训练进度
        if step % 50 == 0:            # 打印误差和实时的w,b值
            print(f"iteration:{step}, loss:{loss}, w:{w}, b:{b}")
    return [b,w]                      # 返回最后一次的w,b
# 主训练函数实现如下:
def main():
    # 加载训练集数据,这些数据是通过真实模拟添加观测误差采样得到的
    lr = 0.01                         # 学习率
    initial_b = 0                     # 初始化b为0
    initial_w = 0                     # 初始化w为0
    num_iterations = 1000
    # 训练优化1000次,返回最优w*,b*和训练Loss的下降过程
    [b,w] = gradient_descent(data, initial_b, initial_w, lr, num_iterations)
    loss = mse(b,w,data)              # 计算最优数值解w,b的均方差
    print(f'Final loss:{loss},w:{w},b:{b}')'''
# one-hot编码
'''import tensorflow as tf                               # 导入TF库
y = tf.constant([0,1,2,3,4])
y = tf.one_hot(y,depth=10)
print(y)'''


import os
import tensorflow as tf                               # 导入TF库
from tensorflow import keras                            # 导入TF子库keras
from tensorflow.keras import layers, optimizers, datasets        # 导入TF子库
(x,y), (x_val, y_val) = datasets.mnist.load_data()              # 加载MNIST数据集
x = 2*tf.convert_to_tensor(x, dtype=tf.float32)/255.-1         # 转换为浮点张量,并缩放到-1~1
y = tf.convert_to_tensor(y, dtype=tf.int32)                    # 转换为整型张量
y = tf.one_hot(y, depth=10)
print(x.shape, y.shape)
train_dataset = tf.data.Dataset.from_tensor_slices((x, y))       # 构建数据集对象
train_dataset = train_dataset.batch(512)                         # 批量训练

# 创建一层网络,设置输出节点数为258,激活函数类型为ReLU
layers.Dense(256, activation = 'relu')
# 利用Sequential 容器封装3个网络层,前网络层的输出默认作为下一层的输入
model = keras.Sequential([                                   # 3个非线性层的嵌套模型
    layers.Dense(256,activation='relu'),                     # 隐藏层1
    layers.Dense(128,activation='relu'),                     # 隐藏层2
    layers.Dense(10)])                                       # 输出层,输出节点数为10
with tf.GradientTape() as tape:                              # 构建梯度记录环境
    # 打平操作,[b,28,28]=>[b,10]
    out = model(x)
    # [b]=>[b,10]
    y_onehot = tf.one_hot(y,depth=10)
    # 计算差的平方和[b,10]
    loss = tf.square(out-y_onehot)
    # 计算每个样本的平均误差,[b]
    loss = tf.reduce_sum(loss)/x.shape[0]
    # Step3 计算参数的梯度w1, w2, w3, b1, b2, b3
grads = tape.gradient(loss,model.trainable_variables)
# 自动计算梯度
grads = tape.gradient(loss, model.trainable_variables)
# w' = w-lr*grad,更新网格参数
optimizer.apply_gradients(zip(grads,model.trainable_variables))
# 每层的张量都需要被优化,故使用Variable类型,并使用截断的正态分布初始化权值张量
# 偏置向量初始化为0即可
# 第一层的参数
w1 = tf.Variable(tf.random.truncated_normal([784,256], stddev=0.1))
b1 = tf.Variable(tf.zeros([256]))
# 第二层的参数
w2 = tf.Variable(tf.random.truncated_normal([256,128], stddev=0.1))
b2 = tf.Variable(tf.zeros([128]))
# 第三层参数
w3 = tf.Variable(tf.random.truncated_normal([128,10], stddev=0.1))
b3 = tf.Variable(tf.zeros([10]))
# 改变视图,[b,28,28]=>[b,28*28]
x = tf.reshape(x,[-1,28*28])
# 第一层计算,[b,784]@[784,256]+[256]=>[b,256]+[256]=>[b,256]+[b,256]
h1 = x@w1 + tf.broadcast_to(b1,[x.shape[0],256])
h1 = tf.nn.relu(h1)                        # 通过激活函数
# 第二层计算,[b,256]=>[b,128]
h2 = h1@w2 +b2
h2 = tf.nn.relu(h2)
# 输出计算层,[b,128]=>[b,10]
out = h2@w3 + b3
# 计算网络输出与标签之间的方差,mse = mean(sum(y-out)^2)
# [b,10]
loss = tf.square(y_onehot - out)
# 误差标量,mean:scalar
loss = tf.reduce_mean(loss)
# 自动梯度,需要求梯度的 张量有[w1,b1,w2,b2,w3,b3]
grads = tape.gradient(loss[w1,b1,w2,b2,w3,b3])
# 梯度更新,assign_sub将当前值减去参数值,原地更新
w1.assign_sub(lr*grads[0])
b1.assign_sub(lr*grads[1])
w2.assign_sub(lr*grads[2])
b2.assign_sub(lr*grads[3])
w3.assign_sub(lr*grads[4])
b3.assign_sub(lr*grads[5])

你可能感兴趣的:(python,机器学习,深度学习)