回归和分类
回归问题得到的结果都是连续的,比如通过学习时间预测成绩
分类问题是将数据分成几类,比如根据邮件信息将邮件分成垃圾邮件和有效邮件两类。
相比于基础的线性回归其实就是增加了一个sigmod函数。
代码
import matplotlib.pyplot as plt
import torch
import pandas as pd
import numpy as np
import torch.nn as nn
# 设定随机种子
torch.manual_seed(2017)
# 从 data.txt 中读入点
with open('./data.txt', 'r') as f:
data_list = [i.split('\n')[0].split(',') for i in f.readlines()]
data = [(float(i[0]), float(i[1]), float(i[2])) for i in data_list]
# 标准化
x0_max = max([i[0] for i in data])
x1_max = max([i[1] for i in data])
data = [(i[0]/x0_max, i[1]/x1_max, i[2]) for i in data]
#把两个类别的点分别保存起来,后续方便绘图
x0 = list(filter(lambda x: x[-1] == 0.0, data)) # 选择第一类的点
x1 = list(filter(lambda x: x[-1] == 1.0, data)) # 选择第二类的点
plot_x0 = [i[0] for i in x0] #第0类点的x坐标
plot_y0 = [i[1] for i in x0]#第0类点的y坐标
plot_x1 = [i[0] for i in x1]#第1类点的x坐标
plot_y1 = [i[1] for i in x1]#第1类点的y坐标
#数据转化为numpy,再转化为tensor
np_data = np.array(data, dtype='float32') # 转换成 numpy array
x_data = torch.from_numpy(np_data[:, 0:2]) # 转换成 Tensor, 大小是 [100, 2]
y_data = torch.from_numpy(np_data[:, 2]).unsqueeze(1) # 转换成 Tensor,大小是 [100, 1]
#定义模型
class LogisticRegression(torch.nn.Module):
def __init__(self):
super(LogisticRegression, self).__init__()
self.linear = torch.nn.Linear(2,1) #这里会自动初始化w和b,所以不需要自己再设置
def forward(self, x):
return self.linear(x) #这里自己第一次写的时候,写成torch.sigmoid(self.linear(x)),其实在后续损失函数中,已经包含了sigmoid函数,所以这里可以直接返回线性层的输出
#实例化
model = LogisticRegression()
#损失函数
criterion = nn.BCEWithLogitsLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1) #优化器,自己也是入门,这里学习率往往按照经验设置,也可以多多尝试设置
# 训练函数
def train(epochs):
model.train()
for e in range(epochs):
optimizer.zero_grad() #梯度归零
y_pred = model(x_data) #前向传播
loss = criterion(y_pred, y_data) #计算损失
loss.backward() #反向传播
optimizer.step() #更新参数
if e % 1000 == 0:
print(f"Epoch {e}, Loss: {loss.item()}")
if __name__ == '__main__':
train(10000)
# 获取训练后的参数
w = model.linear.weight.detach().numpy().flatten()
b = model.linear.bias.detach().numpy().item()
# 计算决策边界 (w1*x1 + w2*x2 + b = 0)
plot_x = np.linspace(0.2, 1, 100)
plot_y = (-w[0] * plot_x - b) / w[1]
# 绘制结果
plt.figure(figsize=(8, 6)) #设置画布
#描点
plt.scatter(plot_x0, plot_y0, c='red', label='Class 0', edgecolors='k')
plt.scatter(plot_x1, plot_y1, c='blue', label='Class 1', edgecolors='k')
#划分割线
plt.plot(plot_x, plot_y, 'g--', linewidth=2, label='Decision Boundary')
plt.title("Logistic Regression Classification")
plt.xlabel("Normalized Feature 1")
plt.ylabel("Normalized Feature 2")
plt.legend()
plt.show()
训练:
最后效果