神经网络应用实例 -- python

# 导包
import numpy as np
# 前向传播函数 H = X * W1 + b1 对应下面程序当中的x, w, b
# 前向传播函数
# - x:包含输入数据的numpy数组,形状为(N,d_1,...,d_k)
# - w:形状为(D,M)的一系列权重
# - b:偏置,形状为(M,)
# 程序中的输入参数x,其形状可以是(N,d_1,...,d_k)
# 比如说x是一个4行2列的二维数组,那么N = 4,d_1 = 2
def affine_forward(x, w, b):
    out = None                       # 初始化返回值为None
    # 下面两句是实现拍扁动作
    N = x.shape[0]                   # 重置输入参数X的形状,N返回的是行
    x_row = x.reshape(N, -1)         # (N,D)
    # 公式的实现
    out = np.dot(x_row, w) + b       # (N,M)
    cache = (x, w, b)                # 缓存值,反向传播时使用
    return out,cache
'''
上面的例子是二维的,也可以有三维的,比如对于一个20*20像素的4张灰度图,
x的形状将是(4,20,20),对应的参数就是N=4,d_1=20,d_2=20。
(这里边第一个参数用N表示,它代表的是同时用于计算前向传播的数据有几组,
后边的参数d_1~d_k代表的是数据本身的形状。)

对于维度高一点的也可以设置为二维,
也就是将(4,20,20)的高维数组变化为(4,20*20)这样的二位数组
为什么要这么做?
是为了方便计算。这样变换之后高维的向量被“拍扁”成一维向量(长度为20*20的一维向量)
,对应的W和b也都是一维的,既统一了参数形式,又不会影响数据的正常使用
'''
# 反向传播函数的书写
# 反向传播函数
# - x:包含输入数据的numpy数组,形状为(N,d_1,...,d_k)
# - w:形状(D,M)的一系列权重
# - b:偏置,形状为(M,)
'''
仿射变换反向传播的最重要三个目的:1、更新参数b的值
2、计算流向下一个节点的数值 3、更新参数b的值
'''
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))
'''
对于训练数据以及训练模型已经确定的网络来说,
为了得到更好的训练效果需要调节的参数就是上述的隐藏层维度、
正则化强度和梯度下降的学习率,以及下一节中的训练循环次数。
'''
# 训练与迭代:训练和迭代一般是通过一个for循环来实现,将参数来进行一系列的更替
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)

详细可以查看:神经网络快速入门

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值