全连接神经网络(前馈神经网络)

目录

一、初步认识全连接神经网络

1、神经元

2、网络结构

3、正向传播算法

 二、反向传播算法

1、理解

2、迭代流程

三、构建神经网络模型的基本步骤

四、线性回归神经网络结构

4.1 数据处理

1、数据导入

2、数据归一化处理

3、数据集划分

4、数据形状变换

4.2 模型设计

4.3 训练配置

4.4 训练过程

4.5 模型保存

 完整代码

 五、全连接神经网络实现手写数字识别代码

1、手写数字识别原理

2、MINST 数据集

3、代码实现

3.1 方法概括

3.2 数据处理


一、初步认识全连接神经网络

在多层神经网络中, 第 N 层的每个神经元都分别与第 N-1 层的神经元相互连接。

1、神经元

这个神经元接收的输入信号为向量(x_1,x_2,x_3,x_4,x_5) , 向量(w_1,w_2,w_3,w_4,w_5)为输入向量的组合权重, b 为偏置项, 是一个标量。

神经元的作用是对输入向量进行加权求和, 并加上偏置项 b, 最后经过激活函数f 变换产生输出y = f\left(\sum_{i=1}^{5} w_i x_i + b\right)   ===>  y = f(w^Tx+b)

2、网络结构

在分类问题中, 神经网络一般有多层:

  • 第一层为输入层, 对应输入向量, 神经元的数量等于特征向量的维数, 输入层不对数据进行处理, 只是将输入向量送入下一层中进行计算。
  • 中间层为隐含层, 可能有多个。
  • 最后是输出层, 神经元的数量等于要分类的类别数, 输出层的输出值被用来做分类预测

  • 第一层是输入层,对应的输入向量为(x_1,x_2,x_3) , 有 3 个神经元, 输入层不对数据做任何处理, 直接原样送入下一层。
  • 中间层有 4 个神经元, 接收的数据为 (x_1,x_2,x_3), 输出向量为 (y_1,y_2,y_3,y_4)
  • 第三层为输出层, 接收的数据为向量(y_1,y_2,y_3,y_4) , 输出向量为(z_1,z_2)

神经网络通过激活函数而具有非线性, 通过调整权重形成不同的映射函数。现实应用中要拟合的函数一般是非线性的, 线性函数无论怎样复合最终还是线性函数, 因此, 必须使用非线性激活函数。

3、正向传播算法

算法公式:u^{(l)} = W^{(l)} z^{(l-1)} + b^{(l)}z^{(l)} = f(u^{(l)})

假设神经网络有 m 层, 正向传播算法的流程为:

 二、反向传播算法

1、理解

假设神经网络有 n_l 层, 第 l 层的神经元个数为 s_l。 第 l 层从第 l - 1 层接收的输入向量为 z^{(l-1)}, 第 l 层的权重矩阵为 w^{(l)}, 偏置向量为b^{(l)}, 输出向量为 z^{(l)}。 该层的输出可以写成如下形式:

(已有推导结论: \nabla_{W} L = \left(\nabla_{u^{(l)}} L\right) {z^{(l-1)}}^T\nabla_{​{z^{(l-1)}}} L = W^T\left(\nabla_{u^{(l)}} L\right) )

损失函数对权重和偏置的梯度:

发现\nabla_{W} L\nabla_{b^{(l)}} L中都存在\nabla_{u^{(l)}} L,因此定义误差项为:

即得到\delta^{(l)}递推公式为:

通过递推公式知\delta^{(l)}\delta^{(l+1)}计算得到,因此需要从后往前计算,当\delta^{(l)}计算出来时\nabla_{W} L\nabla_{b^{(l)}} L也可计算出来,这就称为反向传播

2、迭代流程

均按照一个样本迭代,若有m个样本,公式要除以m,以求平均梯度

  1. 正向传播, 利用当前权重和偏置值, 计算每一层的输出值--确定z^{(l-1)}
  2. 计算输出层的误差项 \delta^{(n_l)}
  3. 反向传播, 计算隐藏层各层的误差项:

    ⊙ 表示元素乘法,前边表示矩阵乘法
  4. 计算损失函数对权重和偏置的梯度:
  5. 用梯度下降法更新权重和梯度:


    如果采用所有样本进行迭代, 根据单个样本损失函数的梯度计算总梯度, 然后求均值即可。

3、常见激活函数

根据上边公式:\delta^{(l)} = (W^{(l+1)})^T \cdot (\delta^{(l+1)}) \odot f'(u^{(l)})

f'(u^{(l)})是激活函数的导数,因此若激活函数倒数好计算,误差项计算就会容易。

下面是几种常用的激活函数及它们的导数:

三、构建神经网络模型的基本步骤

四、线性回归神经网络结构

线性回归模型可以认为是神经网络模型的一种极简特例, 是一个神经元,其只有加权和、没有非线性变换。

4.1 数据处理

1、数据导入

从本地文件或 URL 中读取数据。

data_list = pd.read_csv(filepath)

2、数据归一化处理

使用Z-Score 归一化

data_list = (data_list - data_list.mean()) / data_list.std()

3、数据集划分

将数据集划分成训练集和测试集, 其中训练集用于确定模型的参数, 测试集用于评判模型的效果。

train_size = int(len(data_list) * ratio)
# 生成一个随机排列的整数数组
random_indices = np.random.permutation(len(data_list))
# 使用随机排列的索引列表重新设定 DataFrame 的行顺序
data_list = data_list.iloc[random_indices]
trainset = data_list[:train_size]

4、数据形状变换

如果读取的数据维数与我们的模型输入的输入维数不一致, 我们就需要进行数据形状的变换

X_train = X_train.values
y_train = trainset["MEDV"]
y_train = y_train.values.reshape(-1, 1) #1维变2维,-1表示自动计算行数,1表示列数
X_test = testset.drop("MEDV", axis=1)
X_test = X_test.values
y_test = testset["MEDV"]
y_test = y_test.values.reshape(-1, 1)

4.2 模型设计

如果将输入特征和输出预测值均以向量表示, 输入特征x有 13 个分量,y有 1 个分量, 那么参数权重的形状是 13× 1:W = \begin{bmatrix} w_1 & w_2 & w_3 & \cdots & w_{13} \end{bmatrix}

class Network(object):def __init__(self, num_of_weights):# 随机产生 w 的初始值# 为了保持程序每次运行结果的一致性, 此处设置固定的随机数种子np.random.seed(0)self.w = np.random.randn(num_of_weights, 1) #数学中向量数据是按列存储的self.b = 0def forward(self, x):z = np.dot(x, self.w) + self.breturn z

4.3 训练配置

通过损失函数平衡模型的好坏

    def loss(self, z, y):error = z - ycost = error * errorcost = np.mean(cost)return cost

    4.4 训练过程

    使用梯度下降法寻找最优W和b

    def gradient(self, x, y):z = self.forward(x)gradient_w = (z - y) * x #(z - y)是m*1  x是m*ngradient_w = np.mean(gradient_w, axis=0) #批量梯度下降,对各个样本取得权重求均值gradient_w = gradient_w[:, np.newaxis] #变成列向量gradient_b = (z - y)gradient_b = np.mean(gradient_b)return gradient_w, gradient_bdef update(self, gradient_w, gradient_b, alpha=0.01):self.w = self.w - alpha * gradient_wself.b = self.b - alpha * gradient_b

    训练模型

    def train(self, x, y, iterations=100, alpha=0.01):losses = []for i in range(iterations):z = self.forward(x)L = self.loss(z, y)gradient_w, gradient_b = self.gradient(x, y)self.update(gradient_w, gradient_b, alpha)losses.append(L)if (i + 1) % 10 == 0:print('iter {}, loss {}'.format(i, L))return losses

    调用函数进行模型训练

    # 创建网络
    net = Network(13)
    num_iterations = 1000
    # 启动训练
    losses = net.train(X_train, y_train, iterations=num_iterations,
    alpha=0.01)
    # 画出损失函数的变化趋势
    plot_x = np.arange(num_iterations)
    plot_y = np.array(losses)
    plt.plot(plot_x, plot_y)
    plt.show()

    4.5 模型保存

    将训练好的模型保存用于后续的预测过程。 当需要进行预测时使用训练好的模型进行预测。

    # 模型保存
    params = {"w": net.w.tolist(),"b": net.b
    } #将参数保存到文件
    with open('params.json', 'w') as f:json.dump(params, f, indent=4)# 使用模型进行预测
    net = Network(13)
    with open('params.json', 'r') as f:params = json.load(f)net.w = np.array(params["w"])
    net.b = params["b"]z = net.forward(X_test)

    绘制图像

    # 绘制预测值与真实值的关系图
    x = np.arange(len(y_test))
    fig, ax = plt.subplots()
    ax.plot(x, z, label='predic', color='red')
    ax.plot(x, y_test, label='label', color='blue')
    ax.legend()
    plt.show()

     完整代码

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import json
    import random
    # pip install pandas matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple# 1.数据处理
    # 载入数据集
    def loadData(filepath):""":param filepath: csv:return: X, y"""data_list = pd.read_csv(filepath)# 使用Z-score对数据进行归一化处理data_list = (data_list - data_list.mean()) / data_list.std()return data_listdata_list = loadData('housing.csv')# 划分训练集与测试集
    def splitData(data_list, ratio):train_size = int(len(data_list) * ratio)# 生成一个随机排列的整数数组random_indices = np.random.permutation(len(data_list))# 使用随机排列的索引列表重新设定 DataFrame 的行顺序data_list = data_list.iloc[random_indices]trainset = data_list[:train_size]testset = data_list[train_size:]X_train = trainset.drop("MEDV", axis=1)X_train = X_train.valuesy_train = trainset["MEDV"]y_train = y_train.values.reshape(-1, 1)X_test = testset.drop("MEDV", axis=1)X_test = X_test.valuesy_test = testset["MEDV"]y_test = y_test.values.reshape(-1, 1)return X_train, X_test, y_train, y_testX_train, X_test, y_train, y_test = splitData(data_list, 0.8)class Network(object):def __init__(self, num_of_weights):# 随机产生w的初始值# 为了保持程序每次运行结果的一致性,此处设置固定的随机数种子np.random.seed(0)self.w = np.random.randn(num_of_weights, 1)self.b = 0.def forward(self, x):z = np.dot(x, self.w) + self.breturn zdef loss(self, z, y):error = z - ynum_samples = error.shape[0]cost = error * errorcost = np.sum(cost) / num_samplesreturn costdef gradient(self, x, y):z = self.forward(x)gradient_w = (z - y) * xgradient_w = np.mean(gradient_w, axis=0)gradient_w = gradient_w[:, np.newaxis]gradient_b = (z - y)gradient_b = np.mean(gradient_b)return gradient_w, gradient_bdef update(self, gradient_w, gradient_b, alpha=0.01):self.w = self.w - alpha * gradient_wself.b = self.b - alpha * gradient_bdef train(self, x, y, iterations=100, alpha=0.01):losses = []for i in range(iterations):z = self.forward(x)L = self.loss(z, y)gradient_w, gradient_b = self.gradient(x, y)self.update(gradient_w, gradient_b, alpha)losses.append(L)if (i + 1) % 10 == 0:print('iter {}, loss {}'.format(i, L))return lossesdef SGD_train(self, x, y, num_epochs, batch_size=64, alpha=0.01):indices = list(range(len(x)))random.shuffle(indices)  # 打乱数据索引,以便随机选择样本losses = []for epoch_id in range(num_epochs):# 在每轮迭代开始之前,将训练数据的顺序随机打乱random.shuffle(indices)  # 打乱数据索引,以便随机选择样本# 将训练数据进行拆分,每个mini_batch包含batch_size条的数据loss = 0for start in range(0, len(x), batch_size):end = min(start + batch_size, len(x))batch_indices = indices[start:end]X_batch = x[batch_indices]y_batch = y[batch_indices]a = self.forward(X_batch)L = self.loss(a, y_batch)loss += Lgradient_w, gradient_b = self.gradient(X_batch, y_batch)self.update(gradient_w, gradient_b, alpha)print('Epoch {} / iter {}, loss = {}'.format(epoch_id, start+1, L))losses.append(loss)return losses# 创建网络
    net = Network(13)
    num_iterations = 1000
    # 启动训练
    losses = net.train(X_train, y_train, iterations=num_iterations, alpha=0.01)
    # losses = net.SGD_train(X_train, y_train, num_epochs=num_iterations, batch_size=64, alpha=0.01)# 画出损失函数的变化趋势
    plot_x = np.arange(num_iterations)
    plot_y = np.array(losses)
    plt.plot(plot_x, plot_y)
    plt.show()# 模型保存
    params = {"w": net.w.tolist(),"b": net.b
    }# 将参数保存到文件
    with open('params.json', 'w') as f:json.dump(params, f, indent=4)# 使用模型进行预测
    net = Network(13)
    with open('params.json', 'r') as f:params = json.load(f)net.w = np.array(params["w"])
    net.b = params["b"]z = net.forward(X_test)# 绘制预测值与真实值的关系图
    x = np.arange(len(y_test))
    fig, ax = plt.subplots()
    ax.plot(x, z, label='predic', color='red')
    ax.plot(x, y_test, label='label', color='blue')
    ax.legend()
    plt.show()

     五、全连接神经网络实现手写数字识别代码

    1、手写数字识别原理

    计算机存储数据的最小单位是 bit, 它只有 0 和 1 两种二进制状态, 所以任何数据在计算机中都是以 0 和 1 组成的一堆数字。 那如何让计算机认出图片中的数字是几呢? 灰度图像是一种只包含灰度级别而不包含彩色信息的图像, 灰度级别通常被分为 256 个等级, 即从全黑(灰度值 0) 到全白(灰度值 255), 使用 8位二进制数可以表示从 0 到 255 的 256 个不同的数值, 因此用一个 8 位二进制数表示一个像素。 如下图所示把 0 以外的点连接起来就能看出图片中的是数字 4。

    2、MINST 数据集

    MNIST 数据集是美国国家标准与技术研究院收集整理的大型手写数字数据库,包含 60,000 个示例的训练集以及 10,000 个示例的测试集。 其中的图像的尺寸为 28*28。 采样数据显示如下:

    MNIST 图像文件有一个特定的文件头, 其中包含一些元数据, 这个文件头由 16 字节组成, 它们分别表示:

    • magic_number: 一个魔数, 用于标识文件格式。 对于图像文件, 这个值通常是 0x00000803;
    • num_images: 文件中的图像数量;
    • num_rows: 每张图像的行数(即高度);
    • num_cols: 每张图像的列数(即宽度)。

    3、代码实现

    3.1 方法概括

    使用一个 3 层的全连接神经网络实现手写数字识别, 输入层神经原个数为 784(也就是图片的像素数 28× 28), 隐藏层的神经元个数为 128, 输出层的神经元个数为 10(数字从 0~9 的个数)。 隐藏层的激活函数使用 ReLU, 输出层的激活函数为 softmax。 分别使用批量梯度下降法和随机梯度下降法进行参数优化。

    3.2 数据处理

    # 读取MNIST数据集
    train_images = idx2numpy.convert_from_file('./MNIST/raw/train-images-idx3-ubyte')
    train_labels = idx2numpy.convert_from_file('./MNIST/raw/train-labels-idx1-ubyte')
    test_images = idx2numpy.convert_from_file('./MNIST/raw/t10k-images-idx3-ubyte')
    test_labels = idx2numpy.convert_from_file('./MNIST/raw/t10k-labels-idx1-ubyte')# 将图像数据转换为一维向量,并归一化
    X_train = train_images.reshape(train_images.shape[0], -1) / 255.0
    X_test = test_images.reshape(test_images.shape[0], -1) / 255.0# 将标签进行one-hot编码
    num_classes = 10
    y_train = np.eye(num_classes)[train_labels]
    y_test = np.eye(num_classes)[test_labels]

    one-hot讲解

     3.3 模型设计

    反向传播初始误差项跟所选损失函数有关

    • 使用均方误差(MSE)损失函数对应初始误差项 :

      a^{(L)} 是输出层的激活值,y 是真实标签
    • 使用交叉熵损失函数对应初始误差项 :

      y 是真实标签的one-hot编码
    class NeuralNetwork:def __init__(self, input_size, hidden_size, output_size):self.input_size = input_sizeself.hidden_size = hidden_sizeself.output_size = output_size# 初始化权重self.W1 = np.random.randn(self.input_size, self.hidden_size)self.b1 = np.zeros((1, self.hidden_size))self.W2 = np.random.randn(self.hidden_size, self.output_size)self.b2 = np.zeros((1, self.output_size))def forward(self, X):# 前向传播self.z1 = np.dot(X, self.W1) + self.b1self.a1 = np.maximum(0, self.z1)  # ReLU激活函数self.z2 = np.dot(self.a1, self.W2) + self.b2exp_scores = np.exp(self.z2)    # softmaxself.probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)return self.probsdef backward(self, X, y, learning_rate=0.01):# 反向传播m = X.shape[0]delta3 = self.probs - ydW2 = np.dot(self.a1.T, delta3) / mdb2 = np.sum(delta3, axis=0, keepdims=True) / mdelta2 = np.dot(delta3, self.W2.T) * (self.a1 > 0) #(self.a1 > 0)表示Relu激活函数求导结果,要么是0要么是1dW1 = np.dot(X.T, delta2) / mdb1 = np.sum(delta2, axis=0, keepdims=True) / m# 更新权重self.W1 -= learning_rate * dW1self.b1 -= learning_rate * db1self.W2 -= learning_rate * dW2self.b2 -= learning_rate * db2

    3.4 训练配置

    定义损失函数

    • 在回归问题中常用均方误差作为损失函数;
    • 在分类问题中常用采用交叉熵(Cross-Entropy) 作为损失函数。
        def calculate_loss(self, X, y):# 计算softmax交叉熵损失log_probs = -np.log(self.probs[range(X.shape[0]), np.argmax(y, axis=1)])return np.mean(log_probs)
    常用损失函数

    3.5 训练过程

    # 梯度下降法训练def train(self, X, y, num_epochs=1000, learning_rate=0.01):for epoch in range(num_epochs):# 前向传播和反向传播probs = self.forward(X)self.backward(X, y, learning_rate)loss = self.calculate_loss(X, y)print(f"Epoch {epoch}, Loss: {loss}")# 随机梯度下降法训练def train_SGD(self, X, y, num_epochs=1000, learning_rate=0.01, batch_size=64):  # 增加了batch_size参数indices = list(range(len(X)))random.shuffle(indices)  # 打乱数据索引,以便随机选择样本for epoch in range(num_epochs):# 使用随机顺序遍历数据集for start in range(0, len(X), batch_size):end = min(start + batch_size, len(X))batch_indices = indices[start:end]X_batch = X[batch_indices]y_batch = y[batch_indices]# 前向传播和反向传播probs = self.forward(X_batch)self.backward(X_batch, y_batch, learning_rate)if (start // batch_size) % 100 == 0:loss = self.calculate_loss(X_batch, y_batch)print(f"Epoch [{epoch + 1}/{num_epochs}], step {start + 1}/{len(X)}, Loss: {loss}")
    随机梯度下降算法
    • 梯度下降法计算一步梯度需要对所有样本进行计算
    • 随机梯度下降法(SGD)每次迭代都不使用整个数据集, 而是只选择小批量随机训练样本来计算梯度并更新模型参数。核心概念如下:
      1)minibatch: 每次迭代时抽取出来的一批数据被称为一个 minibatch。
      2)batch_size: 每个 minibatch 所包含的样本数目称为 batch_size。
      3)Epoch: 当程序迭代的时候, 按 minibatch 逐渐抽取出样本, 当把整个数据集都遍历到了的时候, 则完成了一轮训练, 也叫一个 Epoch(轮次)。 启动训练时,可以将训练的轮数 num_epochs 和 batch_size 作为参数传入。

    随机梯度下降算法的过程如下: 



     

    3.6 模型保存

    # 模型保存
    params = {"W1": nn.W1.tolist(),"b1": nn.b1.tolist(),"W2": nn.W2.tolist(),"b2": nn.b2.tolist()
    }
    # 将参数保存到文件
    with open('fcn_params.json', 'w') as f:json.dump(params, f, indent=4)

    4、手动实现代码(完整版)

    import numpy as np
    import idx2numpy  # 用于读取MNIST数据集
    from sklearn.metrics import accuracy_score
    import random
    import json
    import matplotlib.pyplot as plt# 读取MNIST数据集
    train_images = idx2numpy.convert_from_file('./MNIST/raw/train-images-idx3-ubyte')
    train_labels = idx2numpy.convert_from_file('./MNIST/raw/train-labels-idx1-ubyte')
    test_images = idx2numpy.convert_from_file('./MNIST/raw/t10k-images-idx3-ubyte')
    test_labels = idx2numpy.convert_from_file('./MNIST/raw/t10k-labels-idx1-ubyte')# num_images_to_display = 5
    # # for i in range(num_images_to_display):
    # #     plt.imshow(train_images[i], cmap='gray')
    # #     plt.title(f"Label: {train_labels[i]}")
    # #     plt.axis('off')
    # #     plt.show()# 将图像数据转换为一维向量,并归一化
    #第二个维度 -1 表示将所有剩余的维度(即 height 和 width)展平成一维。因此,每个图像将被转换为一个长度为 height * width 的一维数组。
    X_train = train_images.reshape(train_images.shape[0], -1) / 255.0
    X_test = test_images.reshape(test_images.shape[0], -1) / 255.0# 将标签进行one-hot编码
    num_classes = 10
    y_train = np.eye(num_classes)[train_labels]
    y_test = np.eye(num_classes)[test_labels]class NeuralNetwork:def __init__(self, input_size, hidden_size, output_size):self.input_size = input_sizeself.hidden_size = hidden_sizeself.output_size = output_size# 初始化权重self.W1 = np.random.randn(self.input_size, self.hidden_size)self.b1 = np.zeros((1, self.hidden_size))self.W2 = np.random.randn(self.hidden_size, self.output_size)self.b2 = np.zeros((1, self.output_size))def forward(self, X):# 前向传播self.z1 = np.dot(X, self.W1) + self.b1self.a1 = np.maximum(0, self.z1)  # ReLU激活函数self.z2 = np.dot(self.a1, self.W2) + self.b2exp_scores = np.exp(self.z2)    # softmaxself.probs = exp_scores / np.sum(exp_scores, axis=1, keepdims=True)return self.probsdef backward(self, X, y, learning_rate=0.01):# 反向传播m = X.shape[0]delta3 = self.probs - ydW2 = np.dot(self.a1.T, delta3) / mdb2 = np.sum(delta3, axis=0, keepdims=True) / mdelta2 = np.dot(delta3, self.W2.T) * (self.a1 > 0) #(self.a1 > 0)表示Relu激活函数求导结果,要么是0要么是1dW1 = np.dot(X.T, delta2) / mdb1 = np.sum(delta2, axis=0, keepdims=True) / m# 更新权重self.W1 -= learning_rate * dW1self.b1 -= learning_rate * db1self.W2 -= learning_rate * dW2self.b2 -= learning_rate * db2def calculate_loss(self, X, y):# 计算softmax交叉熵损失log_probs = -np.log(self.probs[range(X.shape[0]), np.argmax(y, axis=1)])return np.mean(log_probs)# 梯度下降法训练def train(self, X, y, num_epochs=1000, learning_rate=0.01):for epoch in range(num_epochs):# 前向传播和反向传播probs = self.forward(X)self.backward(X, y, learning_rate)loss = self.calculate_loss(X, y)print(f"Epoch {epoch}, Loss: {loss}")# 随机梯度下降法训练def train_SGD(self, X, y, num_epochs=1000, learning_rate=0.01, batch_size=64):  # 增加了batch_size参数indices = list(range(len(X)))random.shuffle(indices)  # 打乱数据索引,以便随机选择样本for epoch in range(num_epochs):# 使用随机顺序遍历数据集for start in range(0, len(X), batch_size):end = min(start + batch_size, len(X))batch_indices = indices[start:end]X_batch = X[batch_indices]y_batch = y[batch_indices]# 前向传播和反向传播probs = self.forward(X_batch)self.backward(X_batch, y_batch, learning_rate)if (start // batch_size) % 100 == 0:loss = self.calculate_loss(X_batch, y_batch)print(f"Epoch [{epoch + 1}/{num_epochs}], step {start + 1}/{len(X)}, Loss: {loss}")# 定义网络结构和参数
    input_size = 784  # 28*28像素
    hidden_size = 128
    output_size = 10
    batch_size = 64# 创建神经网络实例
    nn = NeuralNetwork(input_size, hidden_size, output_size)# 训练模型
    nn.train_SGD(X_train, y_train, num_epochs=1, learning_rate=0.01, batch_size=batch_size)
    # nn.train(X_train, y_train, num_epochs=1, learning_rate=0.01)# 模型保存
    params = {"W1": nn.W1.tolist(),"b1": nn.b1.tolist(),"W2": nn.W2.tolist(),"b2": nn.b2.tolist()
    }
    # 将参数保存到文件
    with open('fcn_params.json', 'w') as f:json.dump(params, f, indent=4)# 使用模型进行预测
    nn = NeuralNetwork(input_size, hidden_size, output_size)
    with open('fcn_params.json', 'r') as f:params = json.load(f)nn.W1 = np.array(params["W1"])
    nn.b1 = np.array(params["b1"])
    nn.W2 = np.array(params["W2"])
    nn.b2 = np.array(params["b2"])# 预测并评估模型
    test_predictions = np.argmax(nn.forward(X_test), axis=1)test_accuracy = accuracy_score(np.argmax(y_test, axis=1), test_predictions)print(f"Test Accuracy: {test_accuracy:.4f}")

    5、pytorch实现代码(完整版)

    # python --version     3.8.10
    # PyTorch --version   2.3.1
    # torchvision --version 0.18.1
    import torch
    import torch.nn as nn
    import torch.optim as optim
    from torchvision import datasets, transforms# 定义超参数
    input_size = 784  # 28x28
    hidden_size = 128
    num_classes = 10
    num_epochs = 1
    batch_size = 64
    learning_rate = 0.001# 加载和预处理数据
    train_dataset = datasets.MNIST(root='./', train=True, transform=transforms.ToTensor(), download=False)
    test_dataset = datasets.MNIST(root='./', train=False, transform=transforms.ToTensor(), download=False)
    train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
    test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)# 定义全连接神经网络
    class NeuralNet(nn.Module):def __init__(self, input_size, hidden_size, num_classes):super(NeuralNet, self).__init__()self.fc1 = nn.Linear(input_size, hidden_size)self.relu = nn.ReLU()self.fc2 = nn.Linear(hidden_size, num_classes)def forward(self, x):out = self.fc1(x)out = self.relu(out)out = self.fc2(out)return out# 训练模型
    def train(model, train_loader, optimizer, criterion, num_epochs):for epoch in range(num_epochs):for i, (images, labels) in enumerate(train_loader):# 前向传播outputs = model.forward(images.reshape(-1, 28 * 28))loss = criterion(outputs, labels)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()if i % 100 == 0:print(f'Epoch [{epoch + 1}/{num_epochs}], Step [{i + 1}/{len(train_loader)}], Loss: {loss.item()}')# 测试模型
    def predict(model, test_loader):model.eval()  # 设置为评估模式correct = 0total = 0with torch.no_grad():for images, labels in test_loader:outputs = model.forward(images.reshape(-1, 28 * 28))_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()print(f'Accuracy of the network on the 10000 test images: {100 * correct / total} %')model = NeuralNet(input_size, hidden_size, num_classes)
    # 定义损失函数和优化器
    criterion = nn.CrossEntropyLoss()
    # optim.Adam
    optimizer = optim.Adam(model.parameters(), lr=learning_rate)  # SGD
    # 训练模型
    train(model, train_loader, optimizer, criterion, num_epochs=num_epochs)# 保存模型
    torch.save(model.state_dict(), 'fcn_state_dict.pth')# 加载模型
    model.load_state_dict(torch.load('fcn_state_dict.pth'))# 测试模型
    predict(model, test_loader)

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/7469.html

    如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    【C++初阶】第11课—vector

    文章目录 1. 认识vector2. vector的遍历3. vector的构造4. vector常用的接口5. vector的容量6. vector的元素访问7. vector的修改8. vector<vector\<int\>>的使用9. vector的使用10. 模拟实现vector11. 迭代器失效11.1 insert插入数据内部迭代器失效11.2 insert插入…

    Linux查看服务器的内外网地址

    目录&#xff1a; 1、内网地址2、外网地址3、ping时显示地址与真实不一致 1、内网地址 ifconfig2、外网地址 curl ifconfig.me3、ping时显示地址与真实不一致 原因是dns缓存导致的&#xff0c;ping这种方法也是不准确的&#xff0c;有弊端不建议使用&#xff0c;只适用于测试…

    PAT甲级-1024 Palindromic Number

    题目 题目大意 一个非回文数&#xff0c;加上它的翻转数所得的和&#xff0c;进行k次&#xff0c;有可能会得到一个回文数。给出一个数n&#xff0c;限制相加次数为k次&#xff0c;如果小于k次就得到回文数&#xff0c;那么输出该回文数和相加的次数&#xff1b;如果进行k次还…

    xss靶场

    xss-labs下载地址&#xff1a;GitHub - do0dl3/xss-labs: xss 跨站漏洞平台 xss常见触发标签&#xff1a;XSS跨站脚本攻击实例与防御策略-CSDN博客 level-1 首先查看网页的源代码发现get传参的name的值test插入了html里头&#xff0c;还回显了payload的长度。 <!DOCTYPE …

    数据结构——实验七·排序

    欢迎各位大佬们来到Tubishu的博客&#x1f31f; Tubishu是一名计算机本科生&#xff0c;不定期发送一些在学校的成果供佬们消遣~希望能为佬的编程之路添砖加瓦⭐&#x1f525; 求各位大佬们垂怜&#x1f525;点赞评论一下呗&#x1f525;&#x1f525; 本文专栏 ➡️ 数据结构 …

    使用vscode + Roo Code (prev. Roo Cline)+DeepSeek-R1使用一句话需求做了个实验

    摘要 使用vscode、Roo Code和deepseek-reasoner进行了一个实验&#xff0c;尝试使用一句话需求来生成小红书封面图片。工具根据需求提供了详细的架构方案&#xff0c;包括技术栈选择、核心模块划分、目录结构建议等。然后&#xff0c;工具自动化地完成了开发和测试&#xff0c;…

    vscode环境中用仓颉语言开发时调出覆盖率的方法

    在vscode中仓颉语言想得到在idea中利用junit和jacoco的覆盖率&#xff0c;需要如下几个步骤&#xff1a; 1.在vscode中搭建仓颉语言开发环境&#xff1b; 2.在源代码中右键运行[cangjie]coverage. 思路1&#xff1a;编写了测试代码的情况&#xff08;包管理工具&#xff09; …

    基于SpringBoot+WebSocket的前后端连接,并接入文心一言大模型API

    前言&#xff1a; 本片博客只讲述了操作的大致流程&#xff0c;具体实现步骤并不标准&#xff0c;请以参考为准。 本文前提&#xff1a;熟悉使用webSocket 如果大家还不了解什么是WebSocket&#xff0c;可以参考我的这篇博客&#xff1a; rWebSocket 详解&#xff1a;全双工…

    積分方程與簡單的泛函分析8.具連續對稱核的非齊次第II類弗雷德霍姆積分算子方程

    1)def求解具連續對稱核的非齊次第II類弗雷德霍姆積分算子方程 设 是定义在上的连续对称核函数&#xff0c; 非齐次第二类弗雷德霍姆积分算子方程的形式为&#xff1a; &#xff0c; 其中是未知函数&#xff0c;是给定的连续函数&#xff0c;是参数。 2)def其特徵值是否一致…

    RV1126画面质量四:GOP改善画质

    一&#xff0e; 什么是 GOP GOP 实际上就是两个 I 帧的间隔&#xff0c;比方说分辨率是 1920 * 1080 50 帧&#xff0c;假设 GOP 为 5&#xff0c;那就是大概 2s 插入一个 I 帧。我们再 回顾下&#xff0c;H264/H265 的帧结构。H264/H265 分别分为三种帧类型&#xff1a;I 帧、…

    一文了解二叉树的基本概念

    文章目录 二叉树1二叉树的定义及其主要特征1.1二叉树的定义1.2二叉树的特点1.3二叉树的五种形态1.4二叉树与度为2的有序树的区别1.5几个特殊的二叉树1.6二叉树的性质 2二叉树的存储结构2.1二叉树的顺序存储2.2二叉树的链式存储 二叉树 1二叉树的定义及其主要特征 1.1二叉树的定…

    MAX98357A一款数字脉冲编码调制(PCM)输入D类音频功率放大器

    MAX98357A是一款数字脉冲编码调制&#xff08;PCM&#xff09;输入D类音频功率放大器&#xff0c;以下是对其的详细介绍&#xff1a; 一、主要特性 音频性能&#xff1a; 提供D类效率与AB类音频性能。支持高达3.2W&#xff08;4Ω负载&#xff0c;5V供电&#xff09;的输出功率…

    nacos(基于docker最详细安装)

    1、什么是Spring Cloud Spring Cloud是一系列框架的集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发&#xff0c;如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等&#xff0c;都可以用Spring Boot的开发风格做到一键启动和部署。…

    78,【2】BUUCTF WEB .[安洵杯 2019]不是文件

    进入靶场 解题过程 点击最下面的英文字即可上传图片 新建一个文本文档 里面内容为空 更改名字为 1,2,3,4,0x4f3a363a2268656c706572223a323a7b733a393a22002a00696676696577223b623a313b733a393a22002a00636f6e666967223b733a353a222f666c6167223b7d)#.png 知道id1&#x…

    Git 如何将旧仓库迁移新仓库中,但不显示旧的提交记录

    一、异常错误 场景&#xff1a;我想把旧仓库迁移新仓库中&#xff0c;放进去之后&#xff0c;新仓库会显示这个项目之前的所有提交&#xff0c;如何不显示这些旧的提交&#xff1f; 二、原因 我们需要将旧仓库迁移新仓库中&#xff0c;但是又不想在新仓库中显示旧的提交记录…

    Mysql索引(学习自用)

    目录 一、索引概述 优缺点 二、索引结构 1、索引数据结构 2、索引支持结构 3、B树 4、B树 5、hash索引 6、为啥采用B树索引 三、索引分类 四、索引语法 五、索引性能分析 5.1查看执行频率 5.2慢查询日志 5.3profiling 5.4explain 六、索引使用规则 6.1验证索…

    PSD是什么图像格式?如何把PSD转为JPG格式?

    在图形设计的世界里&#xff0c;Photoshop 文档&#xff08;PSD&#xff09;格式是 Adobe Photoshop 的原生文件格式&#xff0c;它允许设计师保存图像中的图层、蒙版、透明度和不同色彩模式等信息。对于需要进一步编辑的设计作品来说&#xff0c;PSD 文件提供了极大的灵活性。…

    基于物联网的风机故障检测装置的设计与实现

    1 系统总体设计方案 通过对风机故障检测装置的设计与实现的需求、可行性进行分析&#xff0c;本设计风机故障检测装置的设计与实现的系统总体架构设计如图2-1所示&#xff0c;系统风机故障检测装置采用STM32F103单片机作为控制器&#xff0c;并通过DS18B20温度传感器、ACS712电…

    全面评测 DOCA 开发环境下的 DPU:性能表现、机器学习与金融高频交易下的计算能力分析

    本文介绍了我在 DOCA 开发环境下对 DPU 进行测评和计算能力测试的一些真实体验和记录。在测评过程中&#xff0c;我主要关注了 DPU 在高并发数据传输和深度学习场景下的表现&#xff0c;以及基本的系统性能指标&#xff0c;包括 CPU 计算、内存带宽、多线程/多进程能力和 I/O 性…

    websocket实现

    由于安卓资源管理器展示的路径不尽相同,各种软件保存文件的位置也不一定一样.对于普通用户上传文件时,查找文件可能是一个麻烦的事情.后来想到了一个办法,使用pc端进行辅助上传. 文章目录 实现思路1.0 实现定义web与客户端通信数据类型和数据格式web端websocket实现web端对客户…