神经网络学习笔记

神经网络


3.1从感知机到神经网络

在这里插入图片描述

  最左边一列称为输入层,最右边一列称为输出层,中间的一层称为中间层(隐藏层)

y = h ( b + w 1 x 1 + w 2 x 2 ) y=h(b+w_1x_1+w_2x_2) y=h(b+w1x1+w2x2)

  将感知机写成更简洁的形式,在这里我们使用一个函数h(x)来表示这种分情况的动作(超过0则输出1,否则输出0)。

  h(x)即是激活函数,激活函数使用了阶跃函数的模型.

a = b + w 1 x 1 + w 2 x 2 a=b+w_1x_1+w_2x_2 a=b+w1x1+w2x2 y = h ( a ) y=h(a) y=h(a)

3.2激活函数

3.2.1 sigmoid函数与阶跃函数

sigmoid函数为:

h ( x ) = 1 ( 1 + e x p ( − x ) ) h(x)={1\over (1+exp(-x))} h(x)=(1+exp(x))1

阶跃函数为:

h ( x ) = { 1 0 < x 0 0 ≤ x h(x)=\left\{ \begin{array}{rcl} 1 & & {0 < x}\\ 0 & & {0 \leq x}\\ \end{array} \right. h(x)={100<x0x

  阶跃函数的实现

#法一:简单实现
import numpy as np
def step_function1(x):
    if x>0:
        return 1
    else:
        return 0
#法二:运用Numpy库
def step_function2(x):
    y=x>0#逻辑结果
    return y.astype(np.int)#将布尔变量转为1和0

  阶跃函数的图形:

在这里插入图片描述

#用matplotlib库画阶跃函数图像
import numpy as np
import matplotlib.pylab as plt
def step_function(x):
    return np.array(x>0,dtype=np.int)

x=np.arange(-5.0,5.0,0.1)#start=-5.0,stop=5.0,step=0.1(-5.0->4.9)
y=step_function(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)#指定y轴的范围
plt.show()

  sigmoid函数的实现与画图

#用matplotlib库画sigmoid函数图像
import numpy as np
import matplotlib.pyplot as plt
def sigmoid(x):
    return 1/(1+np.exp(-x))

x=np.arange(-5.0,5.0,0.1)
y=sigmoid(x)
plt.plot(x,y)
plt.ylim(-0.1,1.1)#y轴范围
plt.show()

  sigmoid函数图像为:

在这里插入图片描述

3.2.2 sigmoid函数与阶跃函数的关系

不同点:阶跃函数只能返回0或1,而sigmoid函数可以返回0.731…、0.880…等实数且具有平滑性。即感知机钟神经元之间流动的是0或1的二元信号,而神经网络中流动的是连续的实数值信号

共同点:两者结构都为“输入小时,输出接近0(为0);随着输入增大,输出向1靠近(变成1)”。也就是说,当输入信号为重要信息时,阶跃函数和sigmoid函数都会输出较大的值;当输入信号为不重要的信息时,两者都输出较小的值。但不管输入信号有多小,或者说有多大,输出信号始终在0到1间。

3.2.3非线性函数

  阶跃函数与sigmoid函数都不是线性函数。神经网络的激活函数必须使用非线性函数

原因:线性函数的问题在于不管如何加深层数,总是存在与之等效的“无隐藏层的神经网络”(如下例),无法发挥多层网络带来的优势。

y ( x ) = h ( h ( h ( x ) ) ) → y ( x ) = c × c × c × x → y = a × x ( a = c 3 ) y(x)=h(h(h(x))) \rightarrow y(x)=c\times c \times c \times x \rightarrow y=a \times x (a=c^3) y(x)=h(h(h(x)))y(x)=c×c×c×xy=a×x(a=c3)

3.2.4 ReLU函数

  ReLU函数可以表示为下面式子:

h ( x ) = { x x > 0 0 x ≤ 0 h(x)=\left\{ \begin{array}{rcl} x & & {x > 0}\\ 0 & & {x \leq 0}\\ \end{array} \right. h(x)={x0x>0x0

#运用numpy实现ReLU函数,用matlplotlib画图
import numpy as np
import matplotlib.pyplot as plt
def relu(x):
    return np.maximum(0,x)

x=np.arange(-5,5,0.1)
y=relu(x)
plt.plot(x,y)
plt.ylim(-1,5)#y轴范围
plt.show()

  ReLU函数的图像:

在这里插入图片描述

3.3多维数组的运算

3.3.1多维数组

#多维数组
import numpy as np
A=np.array([1,2,3,4])
#数组的维数用np.ndim()获得
print(A,np.ndim(A))
#数组的形状可通过实例变量shape获得,返回结果是一个元组
print(A.shape,A.shape[0])

#二维数组(矩阵)
B=np.array([[1,2],[3,4],[5,6]])
print(B,np.ndim(B),B.shape)

3.3.2矩阵乘法

  矩阵乘法的实现:

#运用np.dot()函数计算矩阵乘法
import numpy as np
A=np.array([[1,2],[3,4]])
print(A.shape)
B=np.array([[5,6],[7,8]])
print(B.shape)
print(np.dot(A,B))

注意:在多维数组的乘积运算中,两个矩阵中对应维度的元素个数一致。

3.3.3神经网络的内积

在这里插入图片描述

  以上图简单神经网络为例(该神经网络省略了偏置和激活函数,只有权重)。

#注意X、W、Y的形状
import numpy as np
X=np.array([1,2])
print(X.shape)
W=np.array([[1,3,5],[2,4,6]])
print(W,W.shape)
Y=np.dot(X,W)
print(Y)

3.4 3层神经网络的实现

在这里插入图片描述


3层神经网络:输入层(第0层)有2个神经元,第1个隐藏层(第1层)有3个神经元,第2个隐藏层(第2层)有2个神经元,输出层(第3层)有2个神经元
  巧妙运用NumPy数组,用很少的代码完成神经网络的前向处理。
  先定义符号(即使不记忆也不影响后面的理解)

w 12 ( 1 ) w_{12}^{(1)} w12(1)

在这里插入图片描述

3.4.1输入层

  现在看看从输入层到第1层的第1个神经元的信号传递过程。

在这里插入图片描述

  对于上图有公式:

a 1 ( 1 ) = w 11 ( 1 ) x 1 + w 12 ( 1 ) x 2 + b 1 ( 1 ) a_1^{(1)}=w_{11}^{(1)}x_1+w_{12}^{(1)}x_2+b_1^{(1)} a1(1)=w11(1)x1+w12(1)x2+b1(1)
  若用矩阵乘法计算,则可以表示成:

A ( 1 ) = X W ( 1 ) + B ( 1 ) A^{(1)}=XW^{(1)}+B^{(1)} A(1)=XW(1)+B(1)
其中:

A ( 1 ) = ( a 1 ( 1 ) a 2 ( 1 ) a 3 ( 1 ) ) A^{(1)}= \left( \begin{matrix} a^{(1)}_1 & a_2^{(1)} & a_3^{(1)} \end{matrix} \right) A(1)=(a1(1)a2(1)a3(1))

X = ( x 1 x 2 ) X= \left( \begin{matrix} x_1 & x_2 \end{matrix} \right) X=(x1x2)

B ( 1 ) = ( b 1 ( 1 ) b 2 ( 1 ) b 3 ( 1 ) ) B^{(1)}= \left( \begin{matrix} b_1^{(1)} & b_2^{(1)} & b_3^{(1)} \end{matrix} \right) B(1)=(b1(1)b2(1)b3(1))

W ( 1 ) = ( w 11 ( 1 ) w 21 ( 1 ) w 31 ( 1 ) w 12 ( 1 ) w 22 ( 1 ) w 32 ( 1 ) ) W^{(1)}= \left( \begin{matrix} w_{11}^{(1)} & w_{21}^{(1)} & w_{31}^{(1)} \\ w_{12}^{(1)} & w_{22}^{(1)} & w_{32}^{(1)} \end{matrix} \right) W(1)=(w11(1)w12(1)w21(1)w22(1)w31(1)w32(1))

import numpy as np
def sigmoid(x):
    return 1/(1+np.exp(-x))

X1=np.array([1.0,0.5])
W1=np.array([[0.1,0.3,0.5],[0.2,0.4,0.6]])
B1=np.array([0.1,0.2,0.3])

print(W1.shape)#(2,3)
print(X1.shape)#(2,)
print(B1.shape)#(3,)
A1=np.dot(X1,W1)+B1

3.4.2中间层

  现在我们观察第1层与第2层中激活函数的计算过程,如下图。

在这里插入图片描述

第0层到第1层

在这里插入图片描述

第1层到第2层
#用NumPy实现第0层与第1层与第1层到第2层的信息传递
A1=np.dot(X1,W1)+B1
Z1=sigmoid(A1)

W2=np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
B2=np.array([0.1,0.2])

print(Z1.shape)#(3,)
print(W2.shape)#(3,2)
print(B2.shape)#(2,)

A2=np.dot(Z1,W2)+B2
Z2=sigmoid(A2)

3.4.3输出层

  之后实现第1层到第2层的信号传递,与之前的实现基本相同。但是最后的激活函数和之前的隐藏层有所不同

在这里插入图片描述

def identity_function(x):
    return x

W3=np.array([[0.1,0.3],[0.2,0.4]])
B3=np.array([0.1,0.2])

A3=np.dot(Z2,W3)+B3
Y=identity_function(A3)#或者Y=A3

注意:这里定义的identity_function()函数(恒等函数),并将其作为输出层的激活函数,只是为之前的流程保持一致。

3.4.4代码实现小结

  按照神经网络的实现惯例,对代码进行整理。

import numpy as np
def sigmoid(x):
    return 1/(1+np.exp(-x))

def identity_function(x):
    return x

def init_network():
    network={}
    network['W1']=np.array([[0.1,0.3,0.4],[0.2,0.4,0.6]])
    network['b1']=np.array([0.1,0.2,0.3])
    network['W2']=np.array([[0.1,0.4],[0.2,0.5],[0.3,0.6]])
    network['b2']=np.array([0.1,0.2])
    network['W3']=np.array([[0.1,0.3],[0.2,0.4]])
    network['b3']=np.array([0.1,0.2])
    return network

def forward(network,x):
    W1,W2,W3=network['W1'],network['W2'],network['W3']
    b1,b2,b3=network['b1'],network['b2'],network['b3']

    a1=np.dot(x,W1)+b1
    z1=sigmoid(a1)
    a2=np.dot(z1,W2)+b2
    z2=sigmoid(a2)
    a3=np.dot(z2,W3)+b3
    y=identity_function(a3)
    return y

network=init_network()
x=np.array([1.0,0.5])
y=forward(network,x)
print(y)#[0.31628407 0.69505815]

3.5输出层的设计

  一般来说,回归问题用恒等函数,分类问题用softmax函数
  softmax函数:

y k = e x p ( a k ) ∑ i = 1 n e x p ( a i ) y_k=\frac{exp(a_k)}{\sum_{i=1}^nexp(a_i)} yk=i=1nexp(ai)exp(ak)
  可以由公式看出,输出层的各个神经元都受到所有输入信号的影响。

#softmax函数的实现
import numpy as np
def softmax(x):
    exp_a=np.exp(x)
    sum_exp_a=np.num(exp_a)
    y=exp_a/sum_exp_a
    return y

  但因为softmax实现存在溢出问题,所以将softmax函数进行如下改进:

y k = e x p ( a k ) ∑ i = 1 n e x p ( a i ) = C e x p ( a k ) C ∑ i = 1 n e x p ( a i ) = e x p ( a k + l o g C ) ∑ i = 1 n e x p ( a i + l o g C ) = e x p ( a k + C ′ ) ∑ i = 1 n e x p ( a i + C ′ ) \begin{aligned} y_k={\frac{exp(a_k)}{\sum_{i=1}^nexp(a_i)}} &=\frac{Cexp(a_k)}{C\sum_{i=1}^nexp(a_i)} \\ &=\frac{exp(a_k+logC)}{\sum_{i=1}^nexp(a_i+logC)}\\ &=\frac{exp(a_k+C')}{\sum_{i=1}^nexp(a_i+C')} \end{aligned} yk=i=1nexp(ai)exp(ak)=Ci=1nexp(ai)Cexp(ak)=i=1nexp(ai+logC)exp(ak+logC)=i=1nexp(ai+C)exp(ak+C)
  这里的 C ′ C' C可以用任何值,但是为了防止溢出,一般会使用输入信号中的最大值

#改进版softmax函数的实现
import numpy as np
def softmax(a):
    c=np.max(a)
    exp_a=np.exp(a-c)
    sum_exp_a=np.sum(exp_a)
    y=exp_a/sum_exp_a
    return y

  一般来说,神经网络只把输出值最大的神经元对应的类别作为识别结果。并且,即使使用softmax函数,输出值最大的神经元位置也不会改变,故一般将softmax函数省略。

在这里插入图片描述

3.6手写数字识别

  这里使用MNIST手写数字图像集(由0-9数字图像构成的,训练图像6万张,测试图像1万张)。此文档只根据本章内容说明MNIST数据集的处理部分与推理部分。

在这里插入图片描述

MNIST数据集

3.6.1MNIST数据集读取

  从http://yann.lecun.com/exdb/mnist/下载MNSIT数据集文件,并进行解压。

import numpy as np
import os
import struct
import matplotlib.pyplot as plt
from PIL import Image

#下载并处理数据集格式
def load_mnist(path, kind='train'):
    labels_path = os.path.join(path, '%s-labels.idx1-ubyte' % kind)
    #os.path.join()函数用于路径拼接文件路径
    images_path = os.path.join(path, '%s-images.idx3-ubyte' % kind)
    with open(labels_path, 'rb') as lbpath:
        magic, n = struct.unpack('>II', lbpath.read(8))
        labels = np.fromfile(lbpath, dtype=np.uint8)
    with open(images_path, 'rb') as imgpath:
        magic, num, rows, cols = struct.unpack(">IIII", imgpath.read(16))
        images = np.fromfile(imgpath, dtype=np.uint8).reshape(len(labels), 784)
    return images, labels
 
#数据集的载入-测试数据
def get_data_for_test():
    X_train, y_train = load_mnist('MNIST_data', kind='train')
    print('Rows: %d, columns: %d' % (X_train.shape[0], X_train.shape[1]))
    X_test, y_test = load_mnist('MNIST_data', kind='t10k')
    print('Rows: %d, columns: %d' % (X_test.shape[0], X_test.shape[1]))
    return X_test,y_test

#数据集的载入-训练数据
def get_data_for_train():
    X_train, y_train = load_mnist('MNIST_data', kind='train')
    print('Rows: %d, columns: %d' % (X_train.shape[0], X_train.shape[1]))
    X_test, y_test = load_mnist('MNIST_data', kind='t10k')
    print('Rows: %d, columns: %d' % (X_test.shape[0], X_test.shape[1]))
    return X_train,y_train

3.6.2神经网络的推理处理

def init_network():
    sample_weight_path='sample_weight.pkl'
    with open(sample_weight_path,"rb") as f:
        network=pickle.load(f)
    return network

def sigmoid(x):
    return 1/(1+np.exp(-x))

def softmax(x):
    return x

def predict(network,x):
    W1,W2,W3=network['W1'],network['W2'],network['W3']
    b1,b2,b3=network['b1'],network['b2'],network['b3']
    a1=np.dot(x,W1)+b1
    z1=sigmoid(a1)
    a2=np.dot(z1,W2)+b2
    z2=sigmoid(a2)
    a3=np.dot(z2,W3)+b3
    y=softmax(a3)

    return y
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值