
import numpy as np
# 缺点:感知机设定合适的、能符合预期的输入与输出的权重,是由人工进行的
# 神经网络的一个重要的性质是它可以自动地从数据中学习到合适的权重参数
# 将输入信号的总和转换为输出信号,这种函数一般称为激活函数(activation function)
# 激活函数的作用在于决定如何来激活输入信号的总和
# 激活函数是连接感知机和神经网络的桥梁 ***
"""
一般而言,“朴素感知机”是指单层网络,指的是激活函数使用了“阶跃函数”的模型。
“多层感知机”是指神经网络,即使用sigmoid函数等平滑的激活函数的多层网络。
阶跃函数是指一旦输入超过阈值,就切换输出的函数。
事实上,如果将激活函数从阶跃函数换成其他函数,就可以进入神经网络的世界了。
"""
# sigmoid函数--感知机和神经网络的主要区别就在于这个激活函数
# 神经网络中用sigmoid函数作为激活函数,进行信号的转换,转换后的信号被传送给下一个神经元
"""
sigmoid函数
h(x) = 1/(1 + exp(-x))
式中:exp(-x)表示e**(-x),e是纳皮尔常数2.7182...
什么是函数?--函数就是给定某个输入后,会返回某个输出的转换器
"""
# 阶跃函数的简单实现
"""
表达式
0 (x<=0)
h(x)={
1 (x>0)
"""
# def setp_function(x):
# """
# 阶跃函数:当输入超过0时,输出1,否则输出0
# :param x:输入 只能接受实数(浮点数),参数值不允许取numpy数组
# :return: 输出
# """
# if x > 0:
# return 1
# else:
# return 0
def setp_function(x):
"""
支持numpy数组的实现阶跃函数
:param x:
:return:
"""
y = x > 0
return y.astype(np.int)
# 对numpy数组进行不等号运算后,数组的各个元素都会进行不等号运算,生成一个布尔型数组
# 数组x中大于0的元素被转换为True,小于等于0的元素被转换为False,从而生成一个新的数组y
# 数组y是一个布尔型数组,而阶跃函数是会输出int型的0或1的函数,因此需要把数组y的类型从布尔型转换为int型
# astype()方法可以转换numpy数组的类型,通过参数指定期望的类型,这里是np.int型
x = np.array([-1.0, 1.0, 2.0])
print(x) # [-1. 1. 2.]
y = x > 0
print(y) # y [False True True]
print(type(y)) # <class 'numpy.ndarray'>
y = y.astype(np.int)
print(y) # [0 1 1]
import numpy as np
import matplotlib.pylab as plt
"""
对Pyplot的解说:“方便快速绘图matplotlib通过pyplot模块提供了一套和MATLAB类似的绘图API,
将众多绘图对象所构成的复杂结构隐藏在这套API内部。”
对pylab的解说:“matplotlib还提供了一个名为pylab的模块,
其中包括了许多NumPy和pyplot模块中常用的函数,
方便用户快速进行计算和绘图,十分适合在IPython交互式环境中使用。”
"""
# 阶跃函数的图形
# 阶跃函数以0为界,输出从0切换到1(或者从1切换为0)。它的值呈阶梯式变化,所以称为阶跃函数
def step_function(x):
"""
以numpy数组为参数,对数组的各个元素执行阶跃函数运算,并以数组形式返回运算结果
:param x:numpy数组
:return:0或1
"""
return np.array(x > 0, dtype=np.int)
# np.arange(-5.0, 5.0, 0.1)在-5.0到5.0的范围内,以0.1为单位,生成numpy数组([-5.0,-4.9,...,4.9])
x = np.arange(-5.0, 5.0, 0.1)
y = step_function(x)
# print(x)
# print(y)
plt.plot(x, y)
plt.ylim(-0.1, 1.1) # 指定y轴的范围
# plt.ylim(0, 1.0)
plt.show()
import numpy as np
import matplotlib.pylab as plt
# sigmoid函数的实现
def sigmoid(x):
"""
sigmoid函数--表达式
h(x) = 1/(1 + exp(-x))
式中:exp(-x)表示e**(-x),e是纳皮尔常数2.7182...
:param x: np.exp(-x)对应exp(-x),参数x可以输入一个numpy数组
:return:
"""
return 1 / (1 + np.exp(-x))
x = np.array([-1.0, 1.0, 2.0])
print(sigmoid(x)) # [0.26894142 0.73105858 0.88079708]
# 之所以sigmoid函数的实现能支持numpy数组,秘密就在于numpy的广播功能。
# numpy的广播功能:在标量和numpy数组之间进行运算,标量会和numpy数组的各个元素进行运算,运算结果以numpy数组的形式输出
t = np.array([1.0, 2.0, 3.0])
print(1.0 + t) # [2. 3. 4.]
print(1.0 / t) # [1. 0.5 0.33333333]
# sigmoid函数的图形
x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.show()
"""
sigmoid函数和阶跃函数的比较
区别:
1.首先是“平滑性”不同
sigmoid函数是一条平滑的曲线,输出随着输入发生连续性的变化。
阶跃函数以0为界,输出发生急剧性的变化。
sigmoid函数的平滑性对神经网络的学习具有重要意义
2.相对于阶跃函数只能返回0或1,sigmoid函数可以返回0.731...、0.880...等实数(平滑性不同)
重点:也就是说,感知机中神经元之间流动的是0或1的二元信号,而神经网络中流动的是连续的实数值信号
共同性质:
1.宏观视角看它们具有相似的形状
输入小时,输出就接近0(为0);随着输入增大,输出向1靠近(变成1)。
也就是说:当输入信号为重要信息时,阶跃函数和sigmoid函数都会输出较大的值;当输入信号为不重要信息时,两者都输出较小的值。
2.不管输入信号有多小,或者有多大,输出信号的值都在0到1之间
3.两者均为非线性函数。sigmoid函数是一条曲线,阶跃函数是一条像阶梯一样的折线
"""
"""
在介绍“激活函数”时,经常会看到“非线性函数”和“线性函数”等术语。
函数是输入某个值后悔返回一个值的转换器。想这个转换器输入某个值后,输出值是输入值的常数倍的函数称为
线性函数(用数学式表示为h(x)=cx。c为常数)。新词,线性函数是一条笔直的直线。而非线性函数,顾名思义,
指的是不像线性函数那样呈现出一条直线的函数。
"""
# 神经网络的激活函数必须使用非线性函数,激活函数不能使用线性函数,
# 否则无法发挥叠加层所带来的优势,加深神经网络的层数就没有意义。
# ReLU(Rectified Linear Unit)函数
# 输入大于0时,直接输出该值;输入小于0时,输出0
"""
表达式
x (x > 0)
h(x)={
0 (x <= 0)
"""
def relu(x):
"""
ReLU(Rectified Linear Unit)函数
:param x:
:return:
"""
return np.maximum(0, x) # maximum函数会从输入的数值中选择较大的那个值进行输出

import numpy as np
"""
多维数组就是“数字的集合”
数字排成一列的集合、排成长方形的集合、排成三维状或者(更加一般化的)N维状的集合都称为多维数组
"""
# 一维数组
A = np.array([1, 2, 3, 4])
print(A) # [1 2 3 4]
print(np.ndim(A)) # 1
print(A.shape) # (4,)
print(A.shape[0]) # 4
# 二维数组(矩阵)
A = np.array([[1, 2], [3, 4]])
print(A)
print(A.shape) # (2, 2)
B = np.array([[5, 6], [7, 8]])
print(B)
print(B.shape) # (2, 2)
# np.dot()接收两个numpy数组作为参数,并返回数组的乘积(点积)
# np.dot(A, B)和np.dot(B, A)的结果可能不一样,这是因为矩阵的乘积运算中,操作数(A、B)的顺序不同,结果也会不同
print("A x B的內积为{}".format(np.dot(A, B)))
print("A x B的乘积为{}".format(A*B))
# 2 x 3 矩阵和3 x 2矩阵的乘积--2 x 2
# 重点:矩阵A的第1维的元素个数(列数)必须和矩阵B的第0维的元素个数(行数)相等,如不相等,则无法计算
# 运算结果的矩阵的形状由矩阵A的行数和矩阵B的列数决定
A = np.array([[1, 2, 3], [4, 5, 6]])
print(A.shape)
B = np.array([[1, 2], [3, 4], [5, 6]])
print(B.shape)
print(np.dot(A, B))
# 矩阵A的第1维和矩阵C的第0维元素个数不一致(维度的索引从0开始)--多维数组的乘积运算中,必须使两个矩阵中的对应维度的元素个数一致
# ValueError: shapes (2,3) and (2,2) not aligned: 3 (dim 1) != 2 (dim 0)
# C = np.array([[1, 2], [3, 4]])
# print(np.dot(A, C))
# 二维 * 一维 3 x 2 2 = 3 保持对应维度的元素个数一致(矩阵相乘--左矩阵的列数等于右矩阵的行数)
"""
矩阵相乘:
条件:左矩阵的列数等于右矩阵的行数
操作:同线性代数中矩阵乘法
当使用np.array()定义矩阵时,a,b矩阵相乘:np.dot(a,b)
当使用np.mat()定义矩阵时,a,b矩阵相乘:np.dot(a,b)或a*b
矩阵点乘:
条件:同型矩阵(两矩阵行数和列数相同)
操作:同位置元素相乘
当使用np.array()定义矩阵时,a,b矩阵点乘:a*b或np.multiply(a,b)
当使用np.mat()定义矩阵时,a,b矩阵点乘:np.multiply(a,b)
"""
# 矩阵点乘--对应位置元素相乘,要求矩阵必须使同型矩阵,即两矩阵列数和行数相同
"""
A B
1 2 7 8
3 4 7 8
5 6 7 8
"""
A = np.array([[1, 2], [3, 4], [5, 6]])
print(A.shape)
B = np.array([7, 8])
print(B.shape) # (2,)
print(np.ndim(B))
print(B)
print(np.dot(A, B))
print(A*B)
# 神经网络的內积--使用np.dot(多维数组的点积),可以一次性计算出Y的结果
X = np.array([1, 2])
print(X.shape)
W = np.array([[1, 3, 5], [2, 4, 6]])
print(W.shape)
Y = np.dot(X, W)
print(Y)


import numpy as np
# 3层神经网络的实现
# 重点:神经网络的运算可以作为矩阵运算打包进行,因为神经网络各层的运算是通过矩阵的惩罚运算打包进行的0
# 任何前1层的偏置神经元“1”的偶只有一个。偏置权重的数量取决于后一层的神经元的数量(不包括后一层的偏执神经元“1”)
def sigmoid(x):
"""
隐藏层的激活函数
接收numpy数组,并返回元素个数相同的numpy数组
:param x:
:return:
"""
return 1 / (1 + np.exp(-x))
"""
输出层所用的激活函数,要根据求解问题的性质决定,一般地,
回归问题可使用恒等函数
二元分类的问题--sigmoid函数
多元分类问题--softmax函数
"""
def identify_function(x):
"""
第3层(输出层)的激活函数 -- “恒等函数”,将输入按原样输出
:param x:
:return:
"""
return x


# *****从输入层到第1层的信号传递*****
X = np.array([1.0, 0.5])
W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]]) # W1和X的对应维度的元素个数保持一致
B1 = np.array([0.1, 0.2, 0.3])
print(W1.shape) # (2, 3)
print(X.shape) # (2,)
print(B1.shape) # (3,)
# 隐藏层的加权和(加权信号和偏置的总和)用a表示
A1 = np.dot(X, W1) + B1
# 被激活函数转换后的信号用z表示
Z1 = sigmoid(A1)
print(Z1) # [0.57444252 0.66818777 0.75026011]

# *****从第1层到第2层的信号传递*****
W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
B2 = np.array([0.1, 0.2])
print("Z1的形状{}".format(Z1.shape)) # Z1的形状(3,)
print(W2.shape) # (3, 2)
print(B2.shape) # (2,)
A2 = np.dot(Z1, W2) + B2 # 第1层的输出(Z1)变成了第2层的输入 -- 通过numpy数组,可以将层到层的信号传递过程简单地写出来
Z2 = sigmoid(A2)
print(Z2) # [0.62624937 0.7710107 ]

# *****第2层到输出层的信号传递*****
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 = identify_function(A3) # 或者Y = A3
print(Y)
浙公网安备 33010602011771号