Python跑一个超简单的两层神经网络

记录一下第一次用python跑的神经网络,源代码来自于神经网络15分钟入门!使用python从零开始写一个两层神经网络,具体原理可以查看原文章,写的很详细,写这篇博客主要是记录下遇到的一些问题和学习收获。

1 源码

源码很简单,只需要用到一个numpy库就可以跑程序了。
说明: 以下代码演示了如何用两层神经网络来预测一个点属于第几象限,我们的目的是输入四个坐标,希望系统能够成功的预测出每个坐标所属的是第几象限。

import numpy as np

# 前向传播函数
# - x:包含输入数据的numpy数组,形状为(N,d_1,...,d_k)
# - w:形状为(D,M)的一系列权重
# - b:偏置,形状为(M,)
def affine_forward(x, w, b):
    out = None                       # 初始化返回值为None
    N = x.shape[0]                   # 重置输入参数X的形状
    x_row = x.reshape(N, -1)         # (N,D)
    out = np.dot(x_row, w) + b       # (N,M)
    cache = (x, w, b)                # 缓存值,反向传播时使用
    return out,cache

def affine_backward(dout, cache):
    x, w, b = cache                              # 读取缓存
    dx, dw, db = None, None, None                # 返回值初始化
    dx = np.dot(dout, w.T)                       # (N,D)
    dx = np.reshape(dx, x.shape)                 # (N,d1,...,d_k)
    x_row = x.reshape(x.shape[0], -1)            # (N,D)
    dw = np.dot(x_row.T, dout)                   # (D,M)
    db = np.sum(dout, axis=0, keepdims=True)     # (1,M)
    return dx, dw, db

X = np.array([[2,1],
            [-1,1],
            [-1,-1],
            [1,-1]])      # 用于训练的坐标,对应的是I、II、III、IV象限
t = np.array([0,1,2,3])   # 标签,对应的是I、II、III、IV象限
np.random.seed(1)         # 有这行语句,你们生成的随机数就和我一样了

# 一些初始化参数
input_dim = X.shape[1]     # 输入参数的维度,此处为2,即每个坐标用两个数表示
num_classes = t.shape[0]   # 输出参数的维度,此处为4,即最终分为四个象限
hidden_dim = 50            # 隐藏层维度,为可调参数
reg = 0.001                # 正则化强度,为可调参数
epsilon = 0.001            # 梯度下降的学习率,为可调参数
# 初始化W1,W2,b1,b2
W1 = np.random.randn(input_dim, hidden_dim)     # (2,50)
W2 = np.random.randn(hidden_dim, num_classes)   # (50,4)
b1 = np.zeros((1, hidden_dim))                  # (1,50)
b2 = np.zeros((1, num_classes))                 # (1,4)

for j in range(10000):   #这里设置了训练的循环次数为10000
 # ①前向传播
    H,fc_cache = affine_forward(X,W1,b1)                 # 第一层前向传播
    H = np.maximum(0, H)                                 # 激活
    relu_cache = H                                       # 缓存第一层激活后的结果
    Y,cachey = affine_forward(H,W2,b2)                   # 第二层前向传播
 # ②Softmax层计算
    probs = np.exp(Y - np.max(Y, axis=1, keepdims=True))
    probs /= np.sum(probs, axis=1, keepdims=True)        # Softmax算法实现
 # ③计算loss值
    N = Y.shape[0]                                       # 值为4
    print(probs[np.arange(N), t])                        # 打印各个数据的正确解标签对应的神经网络的输出
    loss = -np.sum(np.log(probs[np.arange(N), t])) / N   # 计算loss
    print(loss)                                          # 打印loss
 # ④反向传播
    dx = probs.copy()                                    # 以Softmax输出结果作为反向输出的起点
    dx[np.arange(N), t] -= 1                             #
    dx /= N                                              # 到这里是反向传播到softmax前
    dh1, dW2, db2 = affine_backward(dx, cachey)          # 反向传播至第二层前
    dh1[relu_cache <= 0] = 0                             # 反向传播至激活层前
    dX, dW1, db1 = affine_backward(dh1, fc_cache)        # 反向传播至第一层前
# ⑤参数更新
    dW2 += reg * W2
    dW1 += reg * W1
    W2 += -epsilon * dW2
    b2 += -epsilon * db2
    W1 += -epsilon * dW1
    b1 += -epsilon * db1

test = np.array([[2, 2], [-2, 2], [-2, -2], [2, -2]])
H, fc_cache = affine_forward(test, W1, b1)  # 仿射
H = np.maximum(0, H)  # 激活
relu_cache = H
Y, cachey = affine_forward(H, W2, b2)  # 仿射
# Softmax
probs = np.exp(Y - np.max(Y, axis=1, keepdims=True))
probs /= np.sum(probs, axis=1, keepdims=True)  # Softmax
print(probs)
for k in range(4):
    print(test[k, :], "所在的象限为", np.argmax(probs[k, :]) + 1)

2 安装numpy库

直接运行是会报错的,如下,这时我们需要导入numpy库,有两种方法。

ModuleNotFoundError: No module named ‘numpy’

方法一:在线安装
在这里插入图片描述
| 图1 |
|–|–|
在这里插入图片描述
| 图2 |
|–|–|
在这里插入图片描述
| 图3 |
|–|–|
不过我通过这种方法安装失败了,然后我就采用了方法二,但是方法二首先需要你的电脑上安装Anaconda。
方法二:将解释器设置为Anaconda
在这里插入图片描述
| 图4 |
|–|–|
点击add选项,然后按下面的操作进行
在这里插入图片描述
| 图5 |
|–|–|
在这里插入图片描述
| 图6 |
|–|–|
设置好之后就可以运行程序了。

3 运行程序

可以看到,当训练次数为10000时,可以成功的预测出每个坐标所属的是哪个象限。
在这里插入图片描述
| 图7 |
|–|–|
当调整训练次数为100时,该模型就不能很好的预测出准确地结果了。在这里插入图片描述
| 图8 |
|–|–|


最后,这个例子仅仅是作为入门使用,作为笔记。

  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,以下是一个简单的三层神经网络Python 代码: ```python import numpy as np # 输入层有 2 个节点,隐藏层有 3 个节点,输出层有 1 个节点 input_layer_size = 2 hidden_layer_size = 3 output_layer_size = 1 # 初始化权重矩阵 theta1 = np.random.rand(hidden_layer_size, input_layer_size+1) # 输入层到隐藏层的权重 theta2 = np.random.rand(output_layer_size, hidden_layer_size+1) # 隐藏层到输出层的权重 # 定义 sigmoid 函数 def sigmoid(z): return 1 / (1 + np.exp(-z)) # 前向传播函数 def forward_propagation(X, theta1, theta2): m = X.shape[0] # 样本数 a1 = np.hstack([np.ones([m, 1]), X]) # 在 X 前面加一列全是 1 的列向量,作为输入层的偏置项 z2 = np.dot(a1, theta1.T) # 第一层神经元的带权输入,即输入层到隐藏层的加权和 a2 = np.hstack([np.ones([m, 1]), sigmoid(z2)]) # 第一层神经元的输出,作为隐藏层的偏置项,再加上全是 1 的列向量,作为隐藏层的偏置项 z3 = np.dot(a2, theta2.T) # 输出层的带权输入,即隐藏层到输出层的加权和 h = sigmoid(z3) # 网络的输出 return a1, z2, a2, z3, h # 反向传播函数 def backward_propagation(X, y, theta1, theta2, learning_rate=0.1): m = X.shape[0] # 样本数 a1, z2, a2, z3, h = forward_propagation(X, theta1, theta2) # 前向传播 delta3 = h - y # 输出层的误差 delta2 = np.dot(delta3, theta2) * sigmoid(z2) * (1 - sigmoid(z2)) # 隐藏层的误差 delta2 = delta2[:,1:] # 去掉偏置项的误差 grad1 = np.dot(delta2.T, a1) / m # 输入层到隐藏层的梯度 grad2 = np.dot(delta3.T, a2) / m # 隐藏层到输出层的梯度 theta1 -= learning_rate * grad1 # 更新输入层到隐藏层的权重 theta2 -= learning_rate * grad2 # 更新隐藏层到输出层的权重 return theta1, theta2 # 训练函数 def train(X, y, theta1, theta2, num_iters=10000): for i in range(num_iters): theta1, theta2 = backward_propagation(X, y, theta1, theta2) return theta1, theta2 # 生成训练数据 X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) y = np.array([[0], [1], [1], [0]]) # 训练神经网络 theta1, theta2 = train(X, y, theta1, theta2) # 预测结果 a1, z2, a2, z3, h = forward_propagation(X, theta1, theta2) print(h) ``` 这个三层神经网络使用 sigmoid 函数作为激活函数,采用随机初始化权重矩阵的方法来训练网络,并使用反向传播算法来计算梯度和更新权重矩阵。最后,我们用生成的训练数据进行训练,并用训练好的网络来预测结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

枫恋蝶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值