鱼C论坛

 找回密码
 立即注册
查看: 220|回复: 11

[技术交流] 关于bp神经网络的问题

[复制链接]
发表于 2024-9-3 10:18:14 | 显示全部楼层 |阅读模式
60鱼币
我从网上抄了一个代码,但是其中不包含保存模型与加载模型的步骤,那么在这个代码中,我是应该保存W和b的值,还是A和Z的值作为训练模型之后后的保存数据,wb和az各自都是什么,cache又是什么
还有一个问题
# 各层网络神经元的参数
layers = [feature_num, 20, 15, 1]
L = len(layers)
我在定义这个[feature_num, 20, 15, 1]的时候,这四个数据是不是表示我有一个输入层两个含隐藏以及一个输出层吗


class NN():
    def __init__(self, layers, data):

        L = len(layers)  # 这个layers是个包含了输入层到输出层的各层神经元个数的列表
        # 设置神经元权重参数和偏置参数
        self.W = {}
        self.b = {}
        for l in range(1, L):
            # print(layers[l])
            self.W["W" + str(l)] = np.mat(np.random.randn(layers[l], layers[l - 1]) * 0.1)
            self.b["b" + str(l)] = np.mat(np.random.randn(layers[l], 1) * 0.1)
        self.A = {}  # 这个字典里存储了输入,和后面各个层的激活值;输出层的激活值在这个字典的最后一个
        self.Z = {}  # 这个字典里存储了从第二层到输出层的没被激活的值
        self.cache = {}  # 这个字典里存储了https://www.cnblogs.com/pinard/p/6422831.html里面各个层δl的值,第一个是输出层的δ

        # 将数据写入类中
        self.data = data

    def forward_activation_02(self, L, flag):  # 这个L是和上面的L一样的,包含了总共层数

        # 初始化输入
        self.A["A0"] = self.inputs

        for l in range(1, L):
            if flag == 0 or l == 1 or l == L - 1:
                self.Z["Z" + str(l)] = self.W["W" + str(l)] * self.A["A" + str(l - 1)] + self.b["b" + str(l)]
                self.A["A" + str(l)] = sigmoid(self.Z["Z" + str(l)])

            else:
                # 启用dropout正则化
                self.d = np.random.rand(self.A["A" + str(l - 1)].shape[0], self.A["A" + str(l - 1)].shape[1])
                self.d = self.d < keep_prob
                self.A["A" + str(l - 1)] = np.multiply(self.A["A" + str(l - 1)], self.d)
                self.A["A" + str(l - 1)] /= keep_prob

                self.Z["Z" + str(l)] = self.W["W" + str(l)] * self.A["A" + str(l - 1)] + self.b["b" + str(l)]

                self.A["A" + str(l)] = sigmoid(self.Z["Z" + str(l)])

        # 更新cache

        for l in reversed(range(1, L)):
            if l == L - 1:
                self.cache["C" + str(l)] = np.multiply(self.A["A" + str(l)] - self.output,
                                                       dsigmoid(self.Z["Z" + str(l)]))

            else:
                self.cache["C" + str(l)] = np.multiply(self.W["W" + str(l + 1)].T * self.cache["C" + str(l + 1)],
                                                       dsigmoid(self.Z["Z" + str(l)]))

        err = np.abs(self.A["A" + str(L - 1)] - self.output)

        return err

    def backPropagate_02(self, learning_rate, L):  # 反向传播
        alpha = learning_rate
        m = self.inputs.shape[1]  # 这是样本数
        for i in range(L):
            l = L - i - 1
            if l > 0:
                self.b['b' + str(l)] = self.b['b' + str(l)] - alpha * 1.0 / m * (
                            self.cache["C" + str(l)] * np.ones((m, 1)))
                self.W['W' + str(l)] = self.W['W' + str(l)] - alpha * 1.0 / m * (
                            self.cache["C" + str(l)] * self.A["A" + str(l - 1)].T)

    def init_prameter(self, batch_size):
        # 每次批量训练batch_size幅图像
        train_dataloader = DataLoader(self.data, batch_size=batch_size, drop_last=False, shuffle=True)
        for train_data in train_dataloader:
            imgs = train_data.numpy()
        batch_xs, batch_ys = imgs[:, :feature_num], imgs[:, feature_num]
        self.inputs = np.mat(batch_xs).transpose()

        self.output = np.mat(sigmoid(batch_ys))

    def train(self, iterations, learning_rate, L, batch_size, train_shape):
        # 批处理训练

        for i in range(iterations):
            if (train_shape % batch_size) != 0:
                print("batch没选对,要能够被train除进")
            for j in range(int(train_shape / batch_size)):
                self.init_prameter(batch_size)
                err = self.forward_activation_02(L, 1)
                self.backPropagate_02(learning_rate, L)

            #############################每训练一轮就在测试集上进行测试
            asdf, aswe = test_data[:, :feature_num], test_data[:, feature_num]
            self.inputs = np.mat(asdf).transpose()
            self.output = np.mat(sigmoid(aswe))
            test_num = self.output.shape[1]

            test_loss = self.forward_activation_02(L, 0)
            print("在训练集上,第", i, "轮迭代误差为", np.sum(err) / batch_size, "在测试集上,第", i, "轮迭代误差为",
                  np.sum(test_loss) / test_num)

            if np.sum(test_loss) / test_num < 0.02 or i == (iterations - 1):
                true_ = self.output.transpose()
                pred_ = self.A["A" + str(L - 1)].transpose()

                print("测试样本的实际结果:", true_)

                print("测试样本的预测结果:", pred_)

                plt.plot(pred_, label="pred")  # 绘制预测关系图
                plt.legend()
                plt.plot(true_, label="true")  # 绘制预测关系图
                plt.legend()
                plt.show()
                break
        return true_, pred_

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-9-3 10:18:26 | 显示全部楼层
关于您的问题,我来逐一回答:

### 1. 保存模型的内容

在BP神经网络中,您需要保存的是模型的**参数**,即权重(W)和偏置(b)。这是因为这些参数定义了您的网络在训练后的状态。激活值(A)和未激活值(Z)是动态的,它们在每次输入新的数据进行前向传播时都会变化,因此不需要保存。以下是一些解释:

- **W(权重):** 网络中连接两个神经元层之间的权重,这些是你需要训练的内容。
- **b(偏置):** 每个神经元附加的一个固定偏移量,也是需要训练的参数。

### 2. cache 的作用

`cache` 通常用来存储在前向传播过程中计算的中间值(如 `Z` 和 `A`),以便在进行反向传播时可以高效地计算梯度。它不需要保存,因为它只是在一次前向和后向传播中使用。

### 3. 定义网络层次的问题

您提到的 `layers` 列表定义了每一层的神经元数量:
layers = [输入层神经元数, 第一个隐藏层神经元数, …, 输出层神经元数]
L = len(layers)  # 表示层数,总共 L 层

如果 `layers` 包含4个元素,例如 `[3, 5, 5, 1]`,这表示一个输入层、两个隐藏层和一个输出层。输入层有3个神经元,第一个隐藏层有5个神经元,第二个隐藏层也有5个神经元,输出层有1个神经元。

### 关于代码中的错误

看起来在您的代码中,有一些地方的写法可能不对,比如:
self.W = np.mat(np.random.randn(layers, layers) * 0.1)
self.b = np.mat(np.random.randn(layers, 1) * 0.1)

`layers` 应该是一个列表,你在定义权重和偏置时应使用 `layers[l-1]` 和 `layers[l]`,例如:
self.W[l] = np.random.randn(layers[l], layers[l-1]) * 0.1
self.b[l] = np.random.randn(layers[l], 1) * 0.1

这样做才能创建正确维度的矩阵。

希望这些解释能够帮助您理解代码和BP神经网络。如果还有其他问题,请随时问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-9-3 10:29:21 | 显示全部楼层
那么我的保存模型是这样写的吗
    def save_model(self, file_path):
        model_data = {
            "weights": self.W,
            "bias": self.b,
        }
        with open(file_path, 'wb') as f:
            pickle.dump(model_data, f)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-9-3 10:29:30 | 显示全部楼层
ShuviDoura 发表于 2024-09-03 10:29
那么我的保存模型是这样写的吗
    def save_model(s ...


是的,您编写的 `save_model` 方法大致是正确的,不过有一点需要注意:在初始化中,`self.W` 和 `self.b` 在定义时使用的是单个矩阵,而不是字典。因此

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-9-3 10:30:31 | 显示全部楼层
那么我要如何读取模型并预测新的输入数据值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-9-3 10:30:37 | 显示全部楼层
ShuviDoura 发表于 2024-09-03 10:30
那么我要如何读取模型并预测新的输入数据值


在你的神经网络实现中,要保存和加载模型,关键是要保存和恢复模型的权重 `W` 和偏置 `b`。这些参数定义了模型在每层中的连接和激活函数的偏移

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-9-3 10:31:41 | 显示全部楼层
FishC 发表于 2024-9-3 10:30
在你的神经网络实现中,要保存和加载模型,关键是要保存和恢复模型的权重 `W` 和偏置 `b`。这些参数定 ...

我加载模型之后,要怎么处理新的输入值,达到预测新的数据的目的
这一部分代码要怎么写
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-9-3 10:31:44 | 显示全部楼层
ShuviDoura 发表于 2024-09-03 10:31
我加载模型之后,要怎么处理新的输入值,达到预测新的 ...


关于您的问题:

### 保存和加载模型

在神经网络中,你一般需要保存和加载权重 (`W`) 和偏置 (`b`) 参数。`A` 和 `Z` 是激活值和未激活的

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-9-3 10:42:06 | 显示全部楼层
我保存得到的W1和W2和 W3的数量为什么不一样
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-9-3 10:48:51 | 显示全部楼层
ShuviDoura 发表于 2024-09-03 10:42
我保存得到的W1和W2和 W3的数量为什么不一样


在您的代码中,`W1`、`W2` 和 `W3` 分别代表不同层之间的权重矩阵。不同层之间的神经元个数不同,因此权重矩阵的尺寸也会

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-9-3 15:03:05 | 显示全部楼层
Traceback (most recent call last):
  File "C:\Users\shiro\Desktop\digital image\PKLlook.py", line 200, in <module>
    pred = predict(nn,data) # 前两个是迭代次数和学习率,需要调整这两个参数寻找最优拟合
  File "C:\Users\shiro\Desktop\digital image\PKLlook.py", line 189, in predict
    nn.forward_activation_02(L=len(nn.W), flag=0)  # 假设flag控制是否应用dropout
  File "C:\Users\shiro\Desktop\digital image\PKLlook.py", line 87, in forward_activation_02
    self.Z["Z" + str(l)] = self.W["W" + str(l)] * self.A["A" + str(l - 1)] + self.b["b" + str(l)]
  File "C:\Users\shiro\Desktop\01\python\lib\site-packages\numpy\matrixlib\defmatrix.py", line 218, in __mul__
    return N.dot(self, asmatrix(other))
  File "<__array_function__ internals>", line 200, in dot
ValueError: shapes (20,3) and (500,4) not aligned: 3 (dim 1) != 500 (dim 0)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-9-3 15:03:10 | 显示全部楼层
ShuviDoura 发表于 2024-09-03 15:03
Traceback (most recent call last):
  File "C:\Use ...


根据错误信息,`ValueError: shapes (20,3) and (500,4) not aligned: 3 (dim 1) != 500 (dim 0)`,出现这个问题的原因是矩阵相乘时

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-21 11:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表