神经网络基础1
关于iPython笔记本
iPython Notebook(是jupyter notebook的前称)是嵌入在网页中的交互式编码环境。运行iPython笔记本的方法为在终端(Mac版)输入命令:1
jupyter notebook
Jupyter notebook的默认端口号为8888,因此在浏览器中输入localhost:8888就能访问。
使用numpy构建基本函数
sigmoid function和np.exp()
sigmoid函数是激活函数的一种,其表达式为:$sigmoid(x) = \frac{1}{1+e^{-x}}$在这里主要对比了np.exp()和math.exp()之间的差别,其目的是为了说明math.exp()主要对单个的数值进行运算,而np.exp()则是对矩阵进行相关的运算。
Sigmoid gradient
sigmoid函数梯度计算公式为:,求梯度的目的主要是要知道曲线在某个方向倾斜程度。在这里将s设为sigmoid(x),然后再计算$\sigma’(x) = s(1-s)$即可。实现代码如下:1
2
3
4
5
6
7
8
9
10
11
12def sigmoid_derivative(x):
"""
功能:求在sigmoid函数中x的梯度
参数:
x -- 一个标量或者numpy数组
返回值:
ds -- 计算出的梯度
"""
s = sigmoid(x)
ds = s * (1 - s)
return ds
重塑数组
np.reshape()用于将X重塑为其他尺寸。在计算机科学中,图像由shape为$(length, height, depth = 3)$的3D数组表示。但是,当你读取图像作为算法的输入时,会将其转换为维度为$(lengthheight3, 1)$的向量。换句话说,将3D阵列“展开”或重塑为1D向量。
练习:实现image2vector()
,该输入采用维度为(length, height, 3)的输入,并返回维度为(length*height*3, 1)的向量。例如,如果你想将形为(a,b,c)的数组v重塑为维度为(a*b, 3)的向量,则可以执行以下操作:1
v = v.reshape((v.shape[0]*v.shape[1], v.shape[2])) # v.shape[0] = a ; v.shape[1] = b ; v.shape[2] = c
实现函数如下:1
2
3
4
5
6
7
8
9
10
11def image2vector(image):
"""
参数:
iamge -- 一个(length, height, depth)类型的numpy数组
返回值:
v -- 一个(length*height*depth, 1)类型的向量
"""
v = image.reshape(image.shape[0] * image.shape[1] * image.shape[2], 1)
return v
行标准化
我们在机器学习和深度学习中使用的另一种常见技术是对数据进行标准化。 由于归一化后梯度下降的收敛速度更快,通常会表现出更好的效果。 通过归一化,也就是将x更改为$ \frac{x}{| x|} $(将x的每个行向量除以其范数)。
以上为作业上内容,但个人还是无法理解归一化后为什么梯度下降的收敛更快。但有一点敢肯定的就是归一化后可以避免计算机计算结果得到大数而导致计算错误,比如算$e^{1000}$后计算机的结果为:
从结果中可以看到计算机报错,如果将1000换成是分数,结果就能求出,这是由计算机本身的性能决定的。
求范数时得用到np.linalg.norm函数。用法在链接中有详细介绍。
练习:执行 normalizeRows()来标准化矩阵的行。 将此函数应用于输入矩阵x之后,x的每一行应为单位长度(即长度为1)向量。
函数实现如下:1
2
3
4
5
6
7
8
9
10
11def normalizeRows(x):
"""
功能:标准化举证的行
参数:
x -- 一个(n, m)类型的numpy矩阵
返回值:
x -- 标准化后的numpy矩阵
"""
x_norm = np.linalg.norm(x, axis = 1, keepdims = True) #求每行的范数
x = x / x_norm #更新x矩阵
return x
广播和softmax函数
在numpy中广播是十分重要的,实现了矩阵和数值之间和矩阵和矩阵之间的快速运算,详情见numpy广播。
练习: 使用numpy实现softmax函数。 你可以将softmax理解为算法需要对两个或多个类进行分类时使用的标准化函数。
Instructions:
$ \text{for } x \in \mathbb{R}^{1\times n} \text{, } softmax(x) = softmax(\begin{bmatrix}
x_1 &&
x_2 &&
… &&
x_n
\end{bmatrix}) = \begin{bmatrix}
\frac{e^{x_1}}{\sum_{j}e^{x_j}} &&
\frac{e^{x_2}}{\sum_{j}e^{x_j}} &&
… &&
\frac{e^{x_n}}{\sum_{j}e^{x_j}}
\end{bmatrix} $$\text{for a matrix } x \in \mathbb{R}^{m \times n} \text{, $x_{ij}$ maps to the element in the $i^{th}$ row and $j^{th}$ column of $x$, thus we have: }$
softmax实现如下:1
2
3
4
5
6
7
8
9
10
11def softmax(x):
"""
参数:
x -- 一个形状为(n, m)的numpy矩阵
返回值:
s -- 一个形状为(n, m)的值为softmax(x)的numpy矩阵
"""
x_exp = np.exp(x)
x_sum = np.sum(x_exp, axis = 1, keepdims = True) #对每行exp后的值求和
s = x_exp / x_sum
return s
之前用pytorch写过手写数字识别的小程序,对于softmax函数映像很深。因为手写数字识别程序主要是通过训练来提高识别到真实数据的概率的方式来输出识别到的数字的。我目前认为softmax主要是将数值归一化来描述概率。
向量化
这里介绍了几个实验,目的就是为了说明用矩阵运算处理数据要比单个数值处理的运算速度更加快,这是由计算机的性能决定的,具体是为什么还待日后研究。
实现L1和L2损失函数
通俗来讲损失函数主要的功能其实就是求神经网络训练的值和真实值之间的差距,训练神经网络的目的其实就是缩小这个差距来使训练出来的值尽可能接近真实值。
L1损失函数公式:
代码实现如下:1
2
3
4
5
6
7
8
9
10def L2(yhat, y):
"""
参数:
yhat -- 预测值
y -- 真实值
返回值:
loss -- 损失函数求得的损失值
"""
loss = np.sum(np.abs(y - yhat))
return loss
L2损失函数公式:
代码实现如下:1
2
3
4
5
6
7
8
9
10def L2(yhat, y):
"""
参数:
yhat -- 预测值
y -- 真实值
返回值:
loss -- 损失函数求得的损失值
"""
loss = np.dot((y - yhat),(y - yhat).T)
return loss