写在前面
本周课程用了两周完成,因为课程让用tensorflow实现,编码时还是更希望自己手写代码实现,而在实现过程中,低估了batchnorm反向计算的难度,导致算法出现各种bug,开始是维度上的bug导致代码无法运行,等代码可以运行时,训练神经网络的时候成本又总会发散,于是静下心来把整个运算的前向和反向过程认真推导了好几遍,期间参考网上一些资料,但感觉都没有把问题真正说清楚,连续三天的推导后,才找到了问题的本质,现将自己写的代码汇总如下。
softmax
概念
softmax相对来说比较简单。其用于处理多元分类问题,而之前学习回归时就在思考怎么解决多元分类问题,并无师自通的实现了onehot编码和hardmax(也是学习softmax时才明白之前实现的是onehot编码和hardmax回归)……
回归模型是Logistic回归模型在多分类问题上的推广,在多分类问题中,输出y的值不再是一个数,而是一个多维列向量,有多少种分类是就有多少维数。激活函数使用的是softmax函数:
损失函数变为:
其反向传播求导公式即为:。注意该公式指的是(代码中写为dZ),而不是!
代码
库:
import numpy as np
import matplotlib.pyplot as plt
训练集数据代码:
'''**********************************************************************'''
#产生数据
def gendata():
np.random.seed(1)
m = 3600 #样本数
N = int(m/2) #分为两类
D = 2 #样本的特征数或维度
X = np.zeros((m,D)) #初始化样本坐标
y = np.zeros((m,1)) #初始化样本标签
Y = np.zeros((m,3)) #初始化样本标签
a = 1.5 #基础半径
for j in range(12):
if j<6:
ix = range((m//12)*j, (m//12)*(j+1))
t = np.linspace((3.14/3)*j+0.01, (3.14/3)*(j+1)-0.01, m//12) #theta角度
r = a + np.random.randn(m//12)*0.15 #radius半径
X[ix] = np.c_[r*np.sin(t), r*np.cos(t)] #生成坐标点
y[ix] = j%3
'''
if j%3==0:
Y[ix] = [1,0,0]
if j%3==1:
Y[ix] = [0,1,0]
if j%3==2:
Y[ix] = [0,0,1]
'''
else:
ix = range((m//12)*j, (m//12)*(j+1))
t = np.linspace((3.14/3)*j+0.01, (3.14/3)*(j+1)-0.01, m//12) #theta角度
r = a*2 + np.random.randn(m//12)*0.15 #radius半径
X[ix] = np.c_[r*np.sin(t), r*np.cos(t)] #生成坐标点
y[ix] = (j+1)%3
'''
if j%3==0:
Y[ix] = [0,1,0]
if j%3==1:
Y[ix] = [0,0,1]
if j%3==2:
Y[ix] = [1,0,0]
'''
Y = np.eye(3)[np.int32(y).reshape(-1)] #该语句实现的功能与上面注释部分相同
return X.T,Y.T,y.T
绘出图形如下:
单次前向函数,删除sigmoid函数(可以不删除……),增加softmax函数,