25天看完了吴恩达的机器学习以及《深度学习入门》和《tensorflow实战》两本书,吴恩达的学习课程只学了理论知识,另外两本书的代码自己敲了一遍,感觉过的太快,趁着跑cGAN的时间把两本书的知识点总结下,然后继续深度学习的课程。欢迎小伙伴一起学习~
另外,本文先把框架搭好,后续会一直补充细节和知识点。
最后,本文参考的书是《深度学习入门》斋藤康毅著,十分推荐初学者使用。
本文的代码地址
损失函数
之所以需要损失函数,是因为我们在优化模型时,需要通过损失函数来更新模型,不选择识别精度的原因是因为识别精度对模型调整的敏感度不如损失函数。
损失函数有均方误差、交叉熵误差,上文提到交叉熵误差通常和softmax一起计算即softmax_with_loss,这个通常用于单分类,而对于多分类,需要使用sigmoid函数,具体请看一文搞懂交叉熵
#均方误差
def mean_squared_error(y, t):
return 0.5 * np.sum((y-t)**2)
#交叉熵误差,具体公式推导可以看下吴恩达的机器学习教学
def cross_entropy_error(y, t):
delta = 1e-7
return -np.sum(t * np.log(y + delta))
这里我们补充一个关于一个batch的交叉熵误差的实现
def cross_entropy_error(y, t): # y是预测值,t是实际值
if y.ndim == 1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
if t.size == y.size:
t = t.argmax(axis=1) # 在列的维度上取获得最大值的索引
batch_size = y.shape[0]
# 这里t为标签形式,y为[batch_size,dim]
return - np.sum(np.log(y[np.arange(batch_size), t])) / batch_size
当t为one-hot形式时,可以用以下代码实现
def cross_entrory_error(y, t):
if y.ndim ==1:
t = t.reshape(1, t.size)
y = y.reshape(1, y.size)
batch_size = y.shape[0]
return -np.sum(t * np.log(y + 1e-7)) / batch_size
梯度
利用微分求梯度的方法计算量太大,而误差反向传播算法的出现提高了计算效率,误差反向传播算法主要基于链式法则,主要有以下几条规则。
1.如果是由a + b = y,则反向传播时a b 的梯度相等,且等于y的梯度
2.如果是a * b = y,则反向传播时a b 的梯度分别为b a,如果是矩阵运算会涉及到矩阵转换
3.复杂的计算可以拆解成简单的元运算来计算梯度
我们以全连接为例:y = xw + b
首先拆解为xw 和 b,按照上述原则,假设y的梯度为1,x*w 和 b的梯度等于y处的梯度也为1,x 和 w的梯度按照第二条原则,则梯度分别为w 和 x,当前计算没有考虑矩阵,如果是矩阵运算w和x都需要做转置,具体见以下代码。此处介绍的很粗糙,仅限于初步理解。后续补几张图哈
下面给出几个重点层包含反向传播算法的类。
全连接层的类
class Affine:
def __init__(self, W, b):
self.W = W
self.b = b
self.x = None
self.original_x_shape = None
self.dW = None
self.db = None
def forward(self, x):
self.original_x_shape = x.shape
x = x.reshape(x.shape[0], -1)
self.x = x
out = np.dot(self.x, self.W) + self.b
return out
def backward(self, dout):
dx = np.dot(dout, self.W.T)
self.dW = np.dot(self.x.T, dout)
self.db = np.sum(dout, axis=0)
# for tensor
dx = dx.reshape(*self.original_x_shape)
return dx