深度学习入门Day2--鱼书学习(1)
前言:《深度学习入门,基于python的理论与实现》是非常好的一本书,封面有一条鱼。
作者是斋藤康毅,东京工业大学毕业,并完成东京大学研究生院课程。现从事计算机视觉与机器学习相关的研究和开发工作。
本系列为该书的学习笔记。
一、感知机
作者提到,感知机也是神经网络(深度学习)的起源算法。所以学习感知机是学习深度学习的重要思想。
1.考虑这样一个感知机
- x1,x2是输入信号,y是输出信号。w1,w2是权重,b是偏置。
当 w 1 x 1 + w 2 x 2 + b w_{1}x_{1}+w_{2}x_{2}+b w1x1+w2x2+b之和超过某个界限,也就是阈值的时候,神经元被激活。 - 权重:控制信号流动难度,值越大,通过的信号越大
- 偏置:调整神经元被激活的容易程度。
2.感知机的局限性
它只能表示一条直线分割的空间,也就是线性空间,无法表示更复杂的曲线分割的非线性空间。
但是如果是多层感知机,也就是再叠加一层,甚至更多层,就可以做到表示非线性空间。
二、神经网络基础
- 相比于刚刚感知机,需要人为设置权重,神经网络的引入就是解放我们的双手,因为神经网络可以自动从数据中学习合适的权重。
- 隐藏层的含义是它的神经元肉眼看不见(和输入输出层不一样)。
鱼书根据实际上拥有权重的层数来表示网络的名称。比如上图,看似由3层神经元组成,实际上只有2层神经元有权重。所以称作“2层网络”。
1.激活函数
a = b + w 1 x 1 + w 2 x 2 (2.1) a = b + w_{1} x_{1} + w_{2} x_{2} \tag{2.1} a=b+w1x1+w2x2(2.1)
y = h ( a ) (2.2) y=h(a)\tag{2.2} y=h(a)(2.2)
首先,(2.1)计算加权输入信号和偏置的总和,记为 a a a。然后式子(2.2)用h()函数把 a a a转换为输出 y y y。
h ( x ) h(x) h(x)会把输入信号的总和转换为输出信号。这种函数一般就称为激活函数。他的作用在于决定如何来激活输入信号的总和。
a a a表示输入信号的总和, h ( ) h() h()表示激活函数, y y y表示输出。
神经网络的激活函数必须是非线性函数,否则加深神经网络层数将没有任何意义
1.1 阶跃函数
以阈值为界限,一旦超过阈值,就切换输出。
阶跃函数(Step Function)
将输入转换为二值输出:当x > 0时输出1,否则输出0参数:x: 输入值,可以是标量、列表或NumPy数组返回:与x形状相同的NumPy数组,元素为0或1
import numpy as np
import matplotlib.pyplot as plt
def step_function(x):return np.array(x>0)
x=np.arange(-5.0,5.0,0.1)#从-5到5,间隔0.1
y=step_function(x)
plt.plot(x,y)
plt.ylim(-0/1,1.1)#指定y轴范围
plt.show()
1.2 sigmoid函数
h ( x ) = 1 1 + e − x (2.3) \ h(x) = \frac{1}{1 + e^{-x}} \tag{2.3} h(x)=1+e−x1(2.3)
Sigmoid函数是一个在生物学中常见的S型函数,也称为S型生长曲线。 在信息科学中,由于其单增以及反函数单增等性质,Sigmoid函数常被用作神经网络的激活函数,将变量映射到0,1之间。----------------“引自百度百科”
我们使用python绘制该曲线。
import numpy as np
import matplotlib.pyplot as plt
# 定义Sigmoid函数
def sigmoid(x):return 1 / (1 + np.exp(-x))
# 生成x轴数据(从-10到10,间隔0.1)
x = np.arange(-10, 10,0.1)
y = sigmoid(x)
plt.plot(x, y, label=r"$\ h(x) = \frac{1}{1 + e^{-x}}$", color='blue', linewidth=2)
plt.xlabel("x", fontsize=12)
plt.ylabel("h(x)", fontsize=12)
plt.legend(fontsize=12) # 显示图例
plt.show()
1.3 sigmoid函数和阶跃函数的比较
- 平滑性:sigmoid函数是一条平滑的曲线。阶跃函数以0为界,输出发出急剧性的变化。
- 输出:输入越小输出越接近0,输入越大输出越接近1。且不管输入信号为多少,输出信号的值都在0到1之间。
- 都是非线性函数: 何为线性函数,指的是输出值是输入值的常数倍的函数。( h ( x ) = c x h(x)=cx h(x)=cx)。因此非线性函数指的是不像线性函数那样呈现出一条直线的函数。
1.4 ReLU函数
比较常用的一种激活函数,输入大于0时,直接输出该值;输入小于等于0时,输出0.
h ( x ) = { x , x > 0 0 , x ≤ 0 h(x) = \begin{cases} x, & x > 0 \\0, & x \leq 0 \end{cases} h(x)={x,0,x>0x≤0
使用Python绘制图像
import numpy as np
import matplotlib.pyplot as plt
def relux(x):return np.maximum(0, x)#取最大值返回
x=np.arange(-6,6,0.1)
y=relux(x)
plt.plot(x,y)
plt.title('relux')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
2 多维矩阵运算
2.1多维数组
详细内容可见上一篇Python基础。
import numpy as np
list1=[1,2,3]
list2=[4,5,6]
list3=[7,8,9]
list4=[10,11,12]
A=np.array(list1)#一维
B=np.array([list1,list2])#二维
C=np.array([[list1,list2],[list3,list4]])#三维
print("A.dim=",np.ndim(A))#A的维数
print("A.shape=",A.shape)#表示A的形状
print("A.shape[0]=",A.shape[0])#表示 A 的第 0 个维度的大小,即 3。print("B.dim=",np.ndim(B))#A的维数
print("B.shape=",B.shape)#表示A的形状
print("B.shape[0]=",B.shape[0])#表示 A 的第 0 个维度的大小,即 3。print("C.dim=",np.ndim(C))#A的维数
print("C.shape=",C.shape)#表示A的形状
print("C.shape[0]=",C.shape[0])#表示 A 的第 0 个维度的大小,即 3。
输出结果:
A.dim= 1
A.shape= (3,)
A.shape[0]= 3
B.dim= 2
B.shape= (2, 3)
B.shape[0]= 2
C.dim= 3
C.shape= (2, 2, 3)
C.shape[0]= 2
A、B、C各是一维、二维、三维数组。
我其实有个比较不靠谱的区分法,看array()里面有几个嵌套 [],一层就是一维,两层就是二维,以此类推。
注意这里A.shape的结果是个元组(tuple)。
2.2 矩阵乘法
回顾线性代数所学内容即可。
A B = C AB=C AB=C
A的列数和B的行数相同。如果A是 n ∗ m n*m n∗m,B是 m ∗ k m*k m∗k,那么C是 n ∗ k n*k n∗k。
下面用Python实现矩阵的乘法,需要用到np.dot()这个函数。
乘积也叫做点积
输入类型 | np.dot(a, b) 行为 |
---|---|
两个一维数组 | 向量内积(返回标量) |
两个二维数组 | 矩阵乘法 |
高维数组 | 张量收缩(沿最后一个轴和倒数第二个轴计算) |
标量 × 数组 | 报错(应使用 a * b 进行逐元素乘法) |
A=np.array([1,2,3])
B=np.array([[1,2,3],[4,5,6],[7,8,9]])
C=np.dot(A,B)
print(C)
结果
[30 36 42]
通过使用np.dot(多维数组的点积),可以一次性计算出C的结果,哪怕C的元素有一千个,也可以一次运算得出。