logistic 回归的手动实现
# 导入包
import torch
import matplotlib.pyplot as plt
import random #用于数据迭代器生成随机数据
# 生成数据集 x1类别0,x2类别1
n_data = torch.ones(50, 2) # 数据的基本形态
x1 = torch.normal(2 * n_data, 1) # shape=(50, 2)
y1 = torch.zeros(50) # 类型0 shape=(50, 1)
x2 = torch.normal(-2 * n_data, 1) # shape=(50, 2)
y2 = torch.ones(50) # 类型1 shape=(50, 1)
# 注意 x, y 数据的数据形式一定要像下面一样(torch.cat是合并数据)
x = torch.cat((x1, x2), 0).type(torch.FloatTensor)
y = torch.cat((y1, y2), 0).type(torch.FloatTensor)
# 数据集可视化
plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=y.data.numpy(), s=100, lw=0, cmap='RdYlGn')
plt.show()
# 数据读取:
def data_iter(batch_size, x, y):
num_examples = len(x)
indices = list(range(num_examples))
random.shuffle(indices) # 样本的读取顺序是随机的
for i in range(0, num_examples, batch_size):
j = torch.LongTensor(indices[i: min(i + batch_size, num_examples)]) #最后一次可能不足一个batch
yield x.index_select(0, j), y.index_select(0, j)
# 参数初始化:
w = torch.ones((2,1))
w.requires_grad_(requires_grad=True)
b = torch.zeros(1, dtype=torch.float32)
b.requires_grad_(requires_grad=True)
def net(x,w,b):
return 1.0 / (1 + torch.exp(-(torch.mm(x,w)+b)))
def loss(y_hat, y):
return (y_hat - y.view(y_hat.size())) ** 2 / 2
# 交叉熵损失(取出正确类别的概率再求和)
def loss_c(y_hat, y):
y_usd=y*(-1)+torch.ones(torch.ones(size=y.size()))
return torch.mm(-torch.log(y_hat),y)+torch.mm(-torch.log(1-y_hat),y_usd)
def sgd(params, lr, batch_size):
for param in params:
param.data -= lr * param.grad / batch_size # 注意这里更改param时用的param.data
def accuracy(y_hat, y): #@save
"""计算预测正确的数量。"""
cmp = y_hat.type(y.dtype) > 0.5 # 大于0.5类别1
result=cmp.type(y.dtype)
acc = 1-float(((result-y).sum())/ len(y))
return acc;
lr = 0.03
num_epochs = 30 # 迭代次数
batch_size = 10 # 批量大小
for epoch in range(num_epochs): # 训练模型一共需要num_epochs个迭代周期
# 在每一个迭代周期中,会使用训练数据集中所有样本一次
for X, y_train in data_iter(batch_size, x, y):
l = loss(net(X, w, b), y_train).sum() # l是有关小批量X和y的损失
# print(net(X, w, b))
l.backward() # 小批量的损失对模型参数求梯度
sgd([w, b], lr, batch_size) # 使用小批量随机梯度下降迭代模型参数
w.grad.data.zero_() # 梯度清零
b.grad.data.zero_() # 梯度清零
train_l = loss(net(x, w, b), y)
print('epoch %d, loss %f' % (epoch + 1, train_l.mean().item()))
分类结果:
import numpy
import matplotlib.pyplot as plt
x_axis = numpy.linspace(-5, 5, 100)
y_devide= (w.detach().numpy()[0]*x_axis+b.detach().numpy())/(-1*w.detach().numpy()[1])
plt.plot(x_axis, y_devide)
plt.scatter(x.data.numpy()[:, 0], x.data.numpy()[:, 1], c=y.data.numpy(), s=100, lw=0, cmap='RdYlGn')
plt.show()