逻辑回归解决二分类问题,分类结果记作0,1
sigmod函数
输入x向量经过神经网络,通过sigmod(x,w)映射为集合(0,1)中的一个实数
二分类问题中,目标是找到一条直线将数据样本分成两类,可简化为:
求P(y=1,w,x) = 1/2时的权重w,其中 w,x为向量
伯努利概型
结果为1的概率 P(y|θ) = θ
结果为0的概率 P(y|θ) = 1-θ
则 P(y|θ) = θ(1-θ)1−
最大似然法与交叉熵
设抛硬币正面概率为θ,反面为1-θ,每次抛硬币看作独立事件互不影响
每次抛硬币都会给出概率尽可能高的结果,每次泡泡出样本结果出现概率累计起来,会趋向最大
假设抛100次硬币,得到包含100个样本的样本集{y1,y2,…,y100}
定义似然度 likehood,即每个样本结果概率的乘积:
似然度必然会趋向最大,因此,需要进行调整以达到最大的似然度
为了方便计算,似然度 左右两侧取对数
令损失函数 L(w) = -logP(y|X,w),让似然度最大,就是让损失函数L(w)最小
则可以使用梯度下降算法使得L(w)最小,求出对应的w向量
利用最大概似法得到的损失函数,称为交叉熵,在PyTorch中,交叉熵损失函数为: nn.CrossEntropyLoss()
from torch import nn,optim
import torch
import matplotlib.pyplot as plt
from time import perf_counter
# 1.数据准备
# 生成两组随机数
# 以 4 和 -4 为期望值,2为标准差的两批随机数,满足正态分布 torch.normal
# 生成两批0,1的目标值数据集
# 将样本集合并作 特征集,结果集作为 标签集
cluster = torch.ones(500,2)
data0 = torch.normal(4*cluster,2)
data1 = torch.normal(-4*cluster,2)
label0 = torch.ones(500)
label1 = torch.zeros(500)
x = torch.cat((data0,data1), ).type(torch.FloatTensor)
y = torch.cat((label0,label1), ).type(torch.LongTensor)
# 2.构造逻辑回归神经网络类(继承nn.Module)
# 构造父类的lineaer方法,处理输入值为(2个特征值,2种结果值)
# 前向传播,处理x格式之后调用sigmod()激活函数,将输入值转换为正态分布
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.linear = nn.Linear(2,2) # 构造2个特征值,2个标签的输入值
def forward(self,x): # 前向传播x传入计算sigmod函数,输出值为预测结果
x = self.linear(x)
x = torch.sigmoid(x)
return x
# 2.创建模型net
CUDA = torch.cuda.is_available()
if CUDA:
net = Net().cuda()
inputs = x.cuda()
target = y.cuda()
else:
net = Net()
inputs = x
target = y
# 3.训练模型
# 优化器采用随机梯度下降算法(SGD),学习率为0.02
# 调用交叉熵损失函数计算损失函数
optimizer = optim.SGD(net.parameters(),lr=0.02)
criterion = nn.CrossEntropyLoss()
def train(model,criterion,optimizer,epochs):
for epoch in range(epochs):
output = model(inputs)
loss = criterion(output,target)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch * 80 == 0:
draw(output,loss)
return model,loss
# 4.绘制图像
def draw(outputs,loss):
if CUDA:
outputs = outputs.cpu()
plt.cla()
outputs = torch.max((outputs),1)[1] # 找出最大的一列向量的第一个
pred_y = outputs.data.numpy().squeeze() # 对数据的维度进行压缩,去掉维数为1的的维度,比如是一行或者一列这种,一个一行三列(1,3)的数去掉第一个维数为一的维度之后就变成(3)行
target_y = y.numpy()
plt.scatter(x.numpy()[:,0],x.numpy()[:,1],c=pred_y,s=10,lw=0,cmap='RdYlGn')
accuracy = sum(pred_y == target_y) /1000.0 # 计算1000个样本中 预测值和目标值一致的准确率
print("accuracy%s"%(accuracy))
plt.text(1.5,4,'Accuracy=%s'%(accuracy),fontdict={'size':20,'color':'blue'})
plt.pause(0.1)
start = perf_counter()
model ,loss = train(net,criterion,optimizer,1000)
finish = perf_counter()
print("训练时间: ",finish)
print("损失值: ",loss.item())
print("参数值: ",list(model.parameters()))