深层神经网络
分类基础理论:
交叉熵是信息论中用来衡量两个分布相似性的一种量化方式
之前讲述二分类的loss函数时我们使用公式-(y*log(y_)+(1-y)*log(1-y_)进行误差计算
y表示真实值,y_表示预测值
def binary_loss(y_pred, y):
logits = (y * y_pred.clamp(1e-12).log() + (1 - y) * (1 - y_pred).clamp(1e-12).log()).mean()
return -logits
交叉熵的一般公式为:
那么二分类时公式可以写作:
其中sigmoid(x)=y_
这就是二分类的loss函数,那么如果我们要进行多分类,比如三分类,十分类,参照此交叉熵方式改进是可行的
而pytorch已经为我们预设了此函数,它将根据我们神经网络输出的分类个数自动进行公式计算
其中每个分类的概率为:
对于输出层的每个输出x1,x2,x3,每个求指数e^x1等等,然后求和,再算出每个值大小占比,即其概率
多分类深层网络
我们可以举个例子,比如mnist手写识别案例,它有十个分类,据此实践交叉熵公式
其中网络的训练是类似的,不同的是loss函数
train_set=mnist.MNIST("./data",train=True,download=True)
test_set=mnist.MNIST('./data',train=False,download=True)
a_data, a_label = train_set[0]
从网络上下载mnist手写数据,然后将其类型转化为tensor类型
查看数据
每张图片28*28,可以看做一组784列的01数据,数据范围为0~255
将所有数据拉平并且标准化,方便输入
from torch.utils.data import DataLoader
def data_tf(x):
x = np.array(x, dtype='float32') / 255
x = (x - 0.5) / 0.5 # 标准化
x = x.reshape((-1,)) # 拉平
x = torch.from_numpy(x)
return x
train_set = mnist.MNIST('./data', train=True, transform=data_tf, download=True) # 重新载入数据集,申明定义的数据变换
test_set = mnist.MNIST('./data', train=False, transform=data_tf, download=True)
当数据集巨大,不能一次导入内存时,往往采取划分迭代方式批次录入,使用数据迭代器
from torch.utils.data import DataLoader
# 数据迭代器
train_data = DataLoader(train_set, batch_size=64, shuffle=True)
test_data = DataLoader(test_set, batch_size=128, shuffle=False)
a, a_label = next(iter(train_data))
数据迭代器是一个对象,从其中取出数据需要使用迭代器,他没有下标
数据已经准备完毕
然后定义神经网络结构和参数,定义损失函数和wb参数优化器,然后进行迭代训练wb
pytroch已经预设了交叉熵函数
mnNet=nn.Sequential(
nn.Linear(784,256),
nn.ReLU(),
nn.Linear(256, 128),
nn.ReLU(),
nn.Linear(128, 64),
nn.ReLU(),
nn.Linear(64, 20),
nn.ReLU(),
nn.Linear(20, 10)
)
losser=nn.CrossEntropyLoss()
optimizer=torch.optim.SGD(mnNet.parameters(),1e-1)
开始迭代训练,其中我们需要统计每个批次的准确率和loss值,方便我们直观的看到准确率和loss的变化
我们需要求出一次迭代数据集训练中所有批次的准确率之和,然后比批次的迭代次数
就得到了每个批次的平均准确率,来作为这一次训练迭代的准确率结果
不实时展示每个批次的准确率和loss是因为单个批次准确率波动范围大,不能准确显示一次迭代训练的效果
接下来我们对数据集进行20次迭代训练
训练和测试不同的地方在于,训练集不需要更新wb参数,也不需要loss进行反向传播
losses=[]
acces=[]
eval_losses=[]
eval_acces=[]
for e in range(20):
train_loss=0
train_acc=0
mnNet.train()
for im,label in train_data:
im=Variable(im)
label=Variable(label)
out=mnNet(im)
loss=losser(out,label)
optimizer.zero_grad()
loss.backward()
optimizer.step()
train_loss+=loss.item()
_,pred=out.max(1)
num_currect=(pred==label).sum()
acc=num_currect/im.shape[0]
train_acc+=acc
losses.append(train_loss/len(train_data))
acces.append(train_acc/len(train_data))
eval_loss=0
eva