【智能计算系统】神经网络基础&代码实现

参考课程:智能计算系统

神经网络中常见的组成部分有:全连接层,激活函数,Softmax层。

全连接层

全连接层输入为一维向量(维度为m),输出为一维向量(维度为n)。前向传播的公式为:

y = W T x + b y=W^Tx+b y=WTx+b

其中,W为二维权重矩阵,维度为 m × n m×n m×n;偏置b是一维向量,维度为n。

以手写数字识别为例,输入的手写数字图像信息,经过第一轮的正向传播后,会产生一个预测结果(结果以概率的形式体现),但这个概率与真实情况的概率(比如数字7的手写图像,理想情况下它为7的概率为1,为其他数字的概率为0)有差别,这样便产生了差值。利用差值来调整网络中的参数(权重、偏置等),得到较为准确的预测结果。

反向传播在理论上通过求偏导的方式来解决。实际应用中通常使用批量随机梯度下降的方法进行反向传播计算。

梯度下降法:通过不断地沿着函数的负梯度方向更新参数,从而逼近函数的局部最小值。(是一种基于一阶导数的优化算法)

代码实现:

# 要引入numpy, os, time等包
class FullyConnectedLayer(object):
    def __init__(self, num_input, num_output):  # 全连接层初始化
        self.num_input = num_input # 输入的一维向量维度
        self.num_output = num_output # 输出的一维向量维度
        print('\tFully connected layer with input %d, output %d.' % (self.num_input, self.num_output))
    def init_param(self, std=0.01):  # 参数初始化
    	# 正态分布随机生成数
    	# loc=0.0 正态分布的均值
    	# scale=std:正态分布的标准差
    	# size:生成随机数的形状,这里是二维数组,行数为self.num_input,列数为self.num_output
    	# 对应于全连接层的权重矩阵
        self.weight = np.random.normal(loc=0.0, scale=std, size=(self.num_input, self.num_output)) 
        self.bias = np.zeros([1, self.num_output]) # 生成全零数组
    def forward(self, input):  # 前向传播计算
        start_time = time.time()
        self.input = input
        #全连接层的前向传播,计算输出结果
        #Y = WX + b
        self.output = np.dot(self.input, self.weight) + self.bias # np.dot:求两个数组的内积
        return self.output
    def backward(self, top_diff):  # 反向传播的计算
        # 全连接层的反向传播,计算参数梯度和本层损失
        # top_diff是“从上一层传递下来的梯度”(损失函数关于上一层输出的偏导数,这些偏导数用于计算当前层的参数梯度(即权重和偏置的更新量)以及进一步传递给下一层)
        self.d_weight = np.dot(self.input.T, top_diff)
        self.batch_size = top_diff.shape[0]
        self.d_bias = np.dot(np.ones(shape=(1,self.batch_size)),top_diff)
        bottom_diff = np.dot(top_diff, self.weight.T)
        return bottom_diff
    def update_param(self, lr):  # 参数更新
        # 对全连接层参数利用参数进行更新
        self.weight = self.weight - lr * self.d_weight
        self.bias = self.bias - lr * self.d_bias
    def load_param(self, weight, bias):  # 参数加载
        assert self.weight.shape == weight.shape
        assert self.bias.shape == bias.shape
        self.weight = weight
        self.bias = bias
    def save_param(self):  # 参数保存
        return self.weight, self.bias

激活函数

为什么要使用激活函数:因为神经网络中每一层的输入输出都是一个线性求和的过程,下一层的输出只是承接了上一层输入函数的线性变换,所以如果没有激活函数,那么无论你构造的神经网络多么复杂,有多少层,最后的输出都是输入的线性组合,纯粹的线性组合并不能够解决更为复杂的问题。而引入激活函数之后,我们会发现常见的激活函数都是非线性的,因此也会给神经元引入非线性元素,使得神经网络可以逼近其他的任何非线性函数,这样可以使得神经网络应用到更多非线性模型中。

参考资料:知乎

ReLU激活函数:x<0时y=0,x>0时y=x。

代码实现:

class ReLULayer(object):
    def __init__(self):
        print('\tReLU layer.')
    def forward(self, input):  # 前向传播的计算
        start_time = time.time()
        self.input = input
        # ReLU层的前向传播,计算输出结果
        # y(i) = max(0, x(i))
        output = np.maximum(0, self.input)
        return output
    def backward(self, top_diff):  # 反向传播的计算
        # ReLU层的反向传播,计算本层损失(计算损失函数对本层的第i个输入的偏导)
        # 公式:x(i)>=0时为:根据损失函数对输出的偏导▽yL计算损失函数对输入的偏导▽xL
        # x(i)<0时取0
        bottom_diff = np.zeros_like(self.input)
        mask = self.input >= 0
        np.putmask(bottom_diff, mask, top_diff)
        #bottom_diff[mask] = top_diff #TypeError: NumPy boolean array indexing assignment requires a 0 or 1-dimensional input, input has 2 dimensions. change
        return bottom_diff

Softmax损失层

Softmax损失层是目前多分类问题中最常用的损失函数层。

Softmax的含义就在于不唯一的确定某一个最大的值,而是为每个输出结果都赋予一个概率值。

  • Softmax层通常作为网络的最后一层,对输出进行归一化,输出分类概率;
  • 凸显其中最大的值并抑制远低于最大值的其他分量;
  • Softmax层输入、输出数据规模相同;
  • 公式: f ( z j ) = e z j ∑ i = 0 n e z i f(z_j)=\frac{e^{z_j}}{\sum_{i=0}^{n}e^{z_i}} f(zj)=i=0neziezj

代码如下:

class SoftmaxLossLayer(object):
    def __init__(self):
        print('\tSoftmax loss layer.')
    def forward(self, input):  # 前向传播的计算
        # softmax 损失层的前向传播,计算输出结果
        input_max = np.max(input, axis=1, keepdims=True) # 找到每行的最大值,并且保持维度不变
        input_exp = np.exp(input - input_max) # 指数运算减去每行的最大值,防止数据溢出
        self.prob = input_exp / np.sum(input_exp, axis=1).reshape(-1, 1) # 计算softmax概率分布
        return self.prob
    def get_loss(self, label):   # 计算损失
        self.batch_size = self.prob.shape[0]
        self.label_onehot = np.zeros_like(self.prob)
        self.label_onehot[np.arange(self.batch_size), label] = 1.0
        loss = -np.sum(np.log(self.prob) * self.label_onehot) / self.batch_size
        return loss
    def backward(self):  # 反向传播的计算
        # TODO:softmax 损失层的反向传播,计算本层损失
        bottom_diff = (self.prob - self.label_onehot) / self.batch_size 
        return bottom_diff
  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智能计算系统(CNN)是一种机器学习技术,用于图像识别和处理任务。CNN实验代码涉及到构建和训练一个CNN模型来完成特定的任务,如图像分类、物体检测等。以下是一个示例的CNN实验代码: 首先,我们需要导入必要的库,如TensorFlow和Keras。然后,我们可以定义一个CNN模型,包含多个卷积层、池化层和全连接层。这些层通过构建一个神经网络,用于学习输入图像的特征并进行分类。 接下来,我们需要加载和预处理数据集。可以使用一些开源数据集,如MNIST手写数字数据集。我们可以使用Keras提供的函数加载数据集,并将其拆分为训练集和测试集。 然后,我们可以对CNN模型进行编译和训练。我们可以选择适当的损失函数和优化器,如交叉熵损失和随机梯度下降优化器。然后,使用模型.fit()函数对训练集进行训练,并设置一些超参数,如批处理大小和迭代次数。 训练完成后,我们可以使用测试集来评估模型的性能。可以使用模型.evaluate()函数计算模型在测试集上的准确率或其他指标。 最后,我们可以使用模型对新的图像进行预测。通过调用模型.predict()函数,将新的图像输入到训练好的模型中,并得到对应的输出。 这只是一个简单的CNN实验代码示例,实际上,CNN的应用非常广泛,可以应用于许多领域,如医学图像处理、自动驾驶等。在实践中,我们还可以调整模型结构、超参数和优化策略,以获得更好的性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值