深度学习DeepLearning - 自学笔记01
数学基础与Python库
1.1 Python - python之禅
import this
# 在Ipython中执行以上代码,可得到如下内容。
The Zen of Python, by Tim Peters
Beautiful is better than ugly. Explicit is better than implicit.
Simple is better than complex. Complex is better than complicated.
Flat is better than nested. Sparse is better than dense. Readability
counts. Special cases aren’t special enough to break the rules.
Although practicality beats purity. Errors should never pass silently.
Unless explicitly silenced. In the face of ambiguity, refuse the
temptation to guess. There should be one-- and preferably only one
–obvious way to do it. Although that way may not be obvious at first unless you’re Dutch. Now is better than never. Although never is often
better than right now. If the implementation is hard to explain,
it’s a bad idea. If the implementation is easy to explain, it may be a
good idea. Namespaces are one honking great idea – let’s do more of
those!
1.2 数学基础
1.2.1 线性代数基础
- 向量
向量就是n个实数组成的有序数组,称为n维向量。
如果没有特别说明,一个n维向量一般表示一个列向量,如 a = [a1 a2 a3 … an]
数组中每一个元素被称为一个分量。
多个向量可以组成一个矩阵。
- 矩阵
矩阵是一个2维的概念。一个向量也可视为大小为 m x 1 的矩阵,如 [a11 a21 … am1],既是一个 m x 1矩阵,又是一个m维向量。
单位矩阵是一种特殊的矩阵,其主对角线上的元素为1,其余元素为0。
n阶单位矩阵In是一个 n x n 的方形矩阵,可以记为 In = diag(1,1, … , 1)。
- 向量的运算
常用向量运算:1. 向量的加减法;2. 向量的点积(内积);这两种运算都需要参与运算的向量长度相同。
- 矩阵的运算
最常见的矩阵运算:加;减;乘;转置(不是除!)。
加减运算要求输入的两个矩阵规模相同(两个矩阵都是m行n列),运算结果为同样规模的矩阵。
乘法有2种:点积;元素乘。元素乘常用!
转置:行变列。
- 向量的范数
范数(Norm):机器学习中衡量一个向量大小。可以理解为一个将向量映射到非负实数的函数。通俗来讲,范数表示的是向量的“长度”。
最常用到的两个范数:L1范数和L2范数。
L2范数,也被称为欧几里得范数,表示从原点出发到向量x确定的点的欧几里得距离。向量的L2范数也被称作向量的模。
L1范数,就是向量中各个元素绝对值的和,用来度量向量的大小。针对问题中零和非零元素之间差异非常重要时使用。
1.2.2 微积分基础
- 导数
导数是反映瞬时变化率的量。核心思想是用平均速度,使得时间无限接近0,以逼近瞬时速度。
- 偏导数
简单理解,偏导数就是对多元函数求其中一个未知数的导数。如,在含x和y的函数中对x求导,此时将未知数y堪称是常数,相当于对未知数x求导。
f(x,y) = ax2+by2+cxy
f’x(x,y) = 2ax+cy
- 向量的导数
向量的求导方法:
- 标量对向量求导
- 向量对向量求导
- 导数法则
- 加减法则
- 乘法法则
- 链式法则
- 常见的向量和矩阵的导数
向量对于其本身的导数为单位向量,这一点与标量的计算相类似。
当一个数或者一个向量对其本身求导,所得结果将是1或者单位向量。
反映到深度学习神经网络中神经元的相互影响上,便可以理解为,一个神经元如果受到自身变化的影响,那么其自身变化多少,影响的大小就有多少。
矩阵A与向量x的乘积对x求偏导数,其结果为矩阵A的转置AT。这个规则常用于求解具有Ax关系的神经元之间的相互连接,也就是后一个神经元如果收到前一个神经元x的影响是Ax,那么当直接相连的前一个神经元增加(或减少)一个单位时,后一个神经元将相应的增加(或减少)A的转置AT个单位。
矩阵A与向量x的转置乘积对x求偏导数,其结果为矩阵A本身。这个规则常用于求解具有xTA关系的神经元之间的相互连接,也就是后一个神经元如果收到前一个神经元x的影响是xTA,那么当直接相连的前一个神经元增加(或减少)一个单位时,后一个神经元将相应的增加(或减少)A的转置A个单位。
- 梯度
之前的导数直接考量的是函数变化率,梯度则从另一个角度考虑函数变化最快的方向。
在机器学习和深度学习中梯度下降法用以求解损失函数的最小值。
梯度的本意是一个向量,该向量表示某一函数在某一点处的方向导数沿着向量方向取得最大值,即函数在该点处沿着该方向(梯度的方向)变化最快,变化率最大(为该梯度的模)。
梯度作为探测损失函数中最小损失的一个“指南针”,避免了寻找一个最小损失值时低效率的枚举情况发生,这对于机器学习和深度学习模型的优化求解具有很重要的意义。
1.3 Python库的操作
1.3.1 Numpy操作
- 基本模块
- array模块
# array的基本操作
import numpy as np
a=[1,2,3,4] # a是python中的list类型
b=np.array(a) # 数组化之后b的类型变为 ayyay
type(b) # b的类型是<type 'numpy.ndarray'>
b.shape # (4,)
b.argmax() # 取最大索引:3
b.max() # 取最大值:4
b.mean() # 取平均值:2.5
# numpy中实现矩阵转置
import numpy as np
x=np.array(np.arange(12).reshape((3,4)))
x
'''
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
'''
t=x.transpose()
t
'''
array([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])
'''
# numpy基础数学运算
import numpy as np
# 绝对值:1
a=np.abs(-1)
# sin函数:1.0
b=np.sin(np.pi/2)
# tanh逆函数:0.5000010715784053
c=np.arctanh(0.462118)
# e为底的指数函数:20.085536923187668
d=np.exp(3)
# 2的3次方:8
f=np.power(2,3)
# 点积:11
g=np.dot([1,2],[3,4])
# 开方:5.0
h=np.sqrt(25)
# 求和:10
l=np.sum([1,2,3,4])
# 平均值:5.5
m=np.mean([4,5,6,7])
# 标准差:0.9682458365518543
p=np.std([1,2,3,2,1,3,2,0])
2. random模块
随机模块可以很方便地做一些快速模拟取验证结论,在神经网络中也能够做一些快速的网络构造。
# random模块相关操作
import numpy as np
# 设置随机数种子
np.random.seed(42)
# 产生一个1x3,[0,1]之间的浮点型随机数
# array([[0.37454012, 0.95071431, 0.73199394]])
np.random.rand(1,3)
# 产生一个[0,1]之间的浮点型随机数
np.random.random()
# 从a中有放回地随机采样7个
# array([7, 2, 3, 7, 3, 3, 5])
a=np.array([1,2,3,4,5,6,7])
np.random.choice(a,7)
# 从a中无放回地随机采样7个
# array([1, 6, 7, 2, 5, 3, 4])
np.random.choice(a,7,replace=False)
# 对a进行乱序并返回一个新的array
# array([6, 3, 7, 1, 5, 4, 2])
b=np.random.permutation(a)
# 生成一个长度为9的随机bytes序列并作为str返回
# b'\xfc\x18\xcf\x01\xeb\xf2\x93nX'
np.random.bytes(9)
- 广播机制
对于array,默认执行对位运算。涉及多个array的对位运算需要array的维度一致,如果一个array的维度与另一个array的维度不一致,则在没有对齐的维度上分别执行对位运算,这种机制称为广播。
# 广播机制的理解
import numpy as np
a = np.array([
[1, 2, 3],
[4, 5, 6]
])
b = np.array([
[1, 2, 3],
[1, 2, 3]
])
'''
维度一样的array,对位运算
array([[2, 4, 6],
[5, 7, 9]])
'''
a+b
c = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[10, 11, 12]
])
d=np.array([2, 2, 2])
'''
广播机制让计算的表达式保持简洁
d和c的每一行分别运算
array([[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14]])
'''
c+d
- 向量化
向量化是提升计算效率的主要手段之一,对于在机器学习中缩短每次训练的时间具有重要意义。
下面的例子通过一个矩阵相乘的例子展示了向量化对于代码计算速度的提升效果。
# 通过一个矩阵相乘的例子展示向量化对于代码计算速度的提升效果
import numpy as np
import time
# 初始化两个1000000维的随机向量v1,v2用于矩阵相乘计算
v1 = np.random.rand(1000000)
v2 = np.random.rand(1000000)
v=0
# 设置tic和toc记录计算开始和结束时间
# 矩阵相乘 - 非向量化版本
tic = time.time()
for i in range(1000000):
v += v1[i] * v2[i]
toc = time.time()
print("非向量化 - 计算时间:" + str((toc - tic) * 1000) + "ms" +"\n")
# 矩阵相乘 - 向量化版本
tic = time.time()
v = np.dot(v1, v2)
toc = time.time()
print("向量化 - 计算时间:" + str((toc - tic) * 1000) + "ms" +"\n")
'''
非向量化 - 计算时间:785.1893901824951ms
向量化 - 计算时间:1.0001659393310547ms
'''
1.3.2 Matplotlib操作
Matplotlib最早是为了可视化癫痫病人的脑皮层电图相关的信号而研发的,因为在函数的设计上参考了MATLAB,所以叫做Matplotlib。
- 图表展示
这里引用机器学习中的梯度下降法来展示图表功能。
import numpy as np
import matplotlib.pyplot as plt
# 目标函数:y=x^2
def func(x):
return np.square(x)
# 目标函数一阶导数也即偏导数:dy/dx=2*x
def dfunc(x):
return 2 * x
def gradient_descent(x_start, func_deri, epochs, learning_rate):
'''
梯度下降法。给定起始点与目标函数的一阶导函数,求在epochs次迭代中x的更新值。
args:
x_start: x的起始点
func_deri: 目标函数的一阶导函数
epochs: 迭代周期
learning_rate: 学习率
return:
xs在每次迭代后的位置(包括起始点),长度为epochs+1
'''
theta_x = np.zeros(epochs + 1)
temp_x = x_start
theta_x[0] = temp_x
for i in range(epochs):
deri_x = func_deri(temp_x)
delta = - deri_x * learning_rate
temp_x = temp_x + delta
theta_x[i+1] = temp_x
return theta_x
def mat_plot():
# 利用matplotlib绘制图像
line_x = np.linspace(-5, 5, 100)
line_y = func(line_x)
x_start = -5
epochs = 5
lr = 0.3
x = gradient_descent(x_start, dfunc, epochs, lr)
color = 'r'
# plot实现绘制的主功能
plt.plot(line_x, line_y, c='b')
plt.plot(x, func(x), c=color, label='lr={}'.format(lr))
plt.scatter(x, func(x), c=color, )
# legend函数显示图例
plt.legend()
# show函数显示
plt.show()
mat_plot()
图中红线为检索过程,点为每次更新的x值所在的点。
- 图像显示
首先读取一个图片并显示,将读取的原图灰度化,进过两次灰度像素变换,形成了两张形状类似但取值范围不同的图案。
显示的时候imshow会自动进行归一化,把最亮的显示为纯白,最暗的值显示为纯黑。这是一种非常方便的设定,尤其是查看深度学习中某个卷积层的响应图时。
import matplotlib.pyplot as plt
# 显示图像
img = plt.imread('https://img-home.csdnimg.cn/images/20201124032511.png')
# plt.imshow(img)
def rgb2gray(rgb):
return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
img = rgb2gray(img)
img1 = img
img2 = 1 - img
# cmap指定为'gray'用来显示灰度图
fig = plt.figure("test")
ax0 = fig.add_subplot(121)
ax0.imshow(img1, cmap='gray')
ax1 = fig.add_subplot(122)
ax1.imshow(img2, cmap='gray')
plt.show()
1.4 本章小结
掌握的知识点:
- 深度学习设计的数学基础知识,如线性代数和微积分等;
- Numpy库和Matplotlib库的基本应用;
- 数学推导、算法设计与编程实现的综合能力。