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

目录

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

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.mzph.cn/bicheng/69069.shtml

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

    相关文章

    MyBatis最佳实践:MyBatis 框架的缓存

    缓存的概念: 在内存中临时存储数据,速度快,可以减少数据库的访问次数经常需要查询,不经常修改的数据,不是特别重要的数据都适合存储到缓存中 缓存的级别: 一级缓存(默认开启):SqlSession 级别 …

    (即插即用模块-特征处理部分) 十八、(TIM 2022) TIF Transformer交互融合模块

    文章目录 1、Transformer Interactive Fusion2、代码实现 paper:DS-TransUNet: Dual Swin Transformer U-Net for Medical Image Segmentation Code:https://github.com/TianBaoGe/DS-TransUNet 1、Transformer Interactive Fusion 对于一些传统的特征融…

    CVE-2025-0411 7-zip 漏洞复现

    文章目录 免责申明漏洞描述影响版本漏洞poc漏洞复现修复建议 免责申明 本文章仅供学习与交流,请勿用于非法用途,均由使用者本人负责,文章作者不为此承担任何责任 漏洞描述 此漏洞 (CVSS SCORE 7.0) 允许远程攻击者绕…

    [操作系统] 深入进程地址空间

    程序地址空间回顾 在C语言学习的时,对程序的函数、变量、代码等数据的存储有一个大致的轮廓。在语言层面上存储的地方叫做程序地址空间,不同类型的数据有着不同的存储地址。 下图为程序地址空间的存储分布和和特性: 使用以下代码来验证一下…

    IGBT的损耗计算的学习【2025/1/24】

    可以通过示波器实测IGBT电压电流波形,然后通过示波器的math功能将电压电流波形乘积后积分求损耗。 软开管:给了导通信号,但是电流并没有从此IGBT流过 IGBT(绝缘栅双极晶体管)的损耗主要分为 导通损耗 和 开关损耗 两部…

    Jmeter使用Request URL请求接口

    简介 在Jmeter调试接口时,有时不清楚后端服务接口的具体路径,可以使用Request URL和cookie来实现接口请求。以下内容以使用cookie鉴权的接口举例。 步骤 ① 登录网站后获取具体的Request URL和cookie信息 通过浏览器获取到Request URL和cookie&#…

    联想电脑怎么设置u盘启动_联想电脑设置u盘启动方法(支持新旧机型)

    有很多网友问联想电脑怎么设置u盘启动,联想电脑设置u盘启动的方法有两种,一是通过bios进行设置。二是通过快捷方式启动进入u盘启动。但需要注意有两种引导模式是,一种是uefi引导,一种是传统的leacy引导,所以需要注意制…

    142.WEB渗透测试-信息收集-小程序、app(13)

    免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于: 易锦网校会员专享课 上一个内容:141.WEB渗透测试-信息收集-小程序、app(12) 软件用法&#xff0c…

    电路研究9.2——合宙Air780EP使用AT指令

    这里正式研究AT指令的学习了,之前只是接触的AT指令,这里则是深入分析AT指令了。 软件的开发方式: AT:MCU 做主控,MCU 发 AT 命令给模组的开发方式,模组仅提供标准的 AT 固件, 所有的业务控制逻辑…

    亚博microros小车-原生ubuntu支持系列:1 键盘控制

    背景:电脑配置不太行,我在ubuntu再运行vmware,里面运行亚博官方的虚拟机镜像ubuntu,系统很卡。基本上8G内存给打满了。还是想把亚博官方的代码迁移出来,之前售后就说除了官方镜像虚拟机,需要自己摸索迁移。…

    第4章 神经网络【1】——损失函数

    4.1.从数据中学习 实际的神经网络中,参数的数量成千上万,因此,需要由数据自动决定权重参数的值。 4.1.1.数据驱动 数据是机器学习的核心。 我们的目标是要提取出特征量,特征量指的是从输入数据/图像中提取出的本质的数 …

    如何获取小程序的code在uniapp开发中

    如何获取小程序的code在uniapp开发中,也就是本地环境,微信开发者工具中获取code,这里的操作是页面一进入就获取code登录,没有登录页面的交互,所以写在了APP.vue中,也就是小程序一打开就获取用户的code APP.…

    Blazor-选择循环语句

    今天我们来说说Blazor选择语句和循环语句。 下面我们以一个简单的例子来讲解相关的语法,我已经创建好了一个Student类,以此类来进行语法的运用 因为我们需要交互性所以我们将类创建在*.client目录下 if 我们做一个学生信息的显示,Gender为…

    科家多功能美发梳:科技赋能,重塑秀发新生

    在繁忙的都市生活中,头皮健康与秀发养护成为了现代人不可忽视的日常课题。近日,科家电动按摩梳以其卓越的性能和创新设计,赢得了广大消费者的青睐。这款集科技与美学于一身的美发梳,不仅搭载了2亿负离子、6000次/分钟的声波振动等前沿技术,更融入了650nm聚能环红光与415nm强劲蓝…

    14-6-2C++的list

    (一&#xff09;list对象的带参数构造 1.list&#xff08;elem);//构造函数将n个elem拷贝给本身 #include <iostream> #include <list> using namespace std; int main() { list<int> lst(3,7); list<int>::iterator it; for(itlst.begi…

    【GoLang】利用validator包实现服务端参数校验时自定义错误信息

    在C/S架构下&#xff0c;服务端在校验请求参数时&#xff0c;若出现参数错误&#xff0c;要响应给客户端一个错误消息&#xff0c;通常我们会统一响应“参数错误”。 但是&#xff0c;如果只是一味的提示参数错误&#xff0c;我并不知道具体是哪个参数错了呀&#xff01;能不能…

    在无法联网的Linux主机或者容器内远程连接主机部署或者容器版的postgresql数据库

    最近做的项目遇到一个问题&#xff0c;需要在Linux主机或者容器内&#xff08;内网环境&#xff0c;无法联网下载postgresql资源&#xff09;&#xff0c;访问远程环境上主机或者容器部署的postgresql数据库&#xff0c;进行数据库数据备份和恢复。 我们知道&#xff0c;直接在…

    C语言内存管理详解

    C语言不像其他高级语言那样提供自动内存管理&#xff0c;它要求程序员手动进行内存的分配和释放。在C语言中&#xff0c;动态内存的管理主要依赖于 malloc、calloc、realloc 和 free 等函数。理解这些函数的用法、内存泄漏的原因及其防止方法&#xff0c;对于编写高效、可靠的C…

    Airflow:解码Airflow执行日期

    执行日期是Apache Airflow&#xff08;用于编排复杂数据管道的开源平台&#xff09;的关键概念。掌握执行日期的概念及其对工作流的影响对于构建高效、可靠和可维护的数据管道至关重要。在本实用指南中&#xff0c;我们将深入研究执行日期在气流中的作用&#xff0c;它们的目的…

    探究 Facebook 隐私安全发展方向,未来走向何方?

    随着社交媒体的普及&#xff0c;隐私和数据安全问题成为了全球关注的焦点。Facebook&#xff0c;作为全球最大的社交平台之一&#xff0c;其隐私安全问题尤其引人注目。近年来&#xff0c;随着用户数据泄露事件的不断发生&#xff0c;Facebook 不断调整其隐私政策&#xff0c;探…