这是我入手Pytorch的第一个个实战,那时候看起来好多代码,几十行,啥时候能看懂啊,但是CSDN是个万能库,基本上什么代码在里面都可搜查到,而且这个程序的代码本身也没有多少,所以后来就都弄明白了。现在看起来也许很简单,也没什么核心内容,但毕竟那是自己走过的路,只有走过来了,才会说:好简单。
这是一个简单的基于逻辑回归算法模型的文本分类,但数据集比较少,所以结果并不是很好。因为我是本着学习代码取看的,就没有纠结数据集的问题。程序里面的print()是为了更好的理解每一步。
下面,直接附上代码,以及一些注解。
import torch
import numpy as np
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
1.数据处理
with open('D:\pythonb\data1.txt','r') as f:
data_list = f.readlines() #读取所有返回一个列表,text每一行表示一个整体
# print('原数据集:',data_list)
'''
str.split(str="",num=string.count(str))[n]
str:表示为分隔符;num:表示分割次数;[n]:表示选取第n个分片
'''
# for i in data_list:
# print(i) #67.37202754570876, 42.83843832029179,0
data_list = [i.split('\n')[0] for i in data_list] #以'\n'为分隔符分割,并取第一个分片返回列表
# print('去掉每一行之后的换行符:',data_list)
data_list = [i.split(',') for i in data_list] #通过分隔符','对字符串进行切片,并返回分割后的字符串列表(list)
# print('分隔后的数据列表:',data_list)
data = []
# print(data)
2.过滤掉丢失的数据
for i in data_list:
# print(i) #[['67.37202754570876', ' 42.83843832029179', '0']
# print(i[0], #67.37202754570876
# '\n',i[1], #42.83843832029179
# '\n',i[2]) #0
if len(i) != 1:
data.append(i) #给空列表:data[]添加数据
# print(data)
# []
# [['67.37202754570876', ' 42.83843832029179', '0']]
# [(67.37202754570876, 42.83843832029179, 0.0)......['89.67677575072079', '65.79936592745237', '1']]
data=[(float(i[0]),float(i[1]),float(i[2])) for i in data]
# print(data) #[(67.37202754570876, 42.83843832029179, 0.0)......(61.83020602312595, 50.25610789244621, 0.0)]
3.制作样本特征和样本标签
x_data=[[i[0],i[1]] for i in data]
# print('特征x0,x1:',x_data)
x_data=np.array(x_data) #生成矩阵
# print('x_data的np矩阵形式:',x_data)
x_data=torch.from_numpy(x_data) #numpy数据转换成tensor
# print('x_data的tensor矩阵形式:',x_data)
x_data=x_data.float()
# print('样本特征:',x_data)
y_data = [[i[2]] for i in data]
y_data = np.array(y_data)
y_data = torch.from_numpy(y_data) # numpy数据转换成tensor
y_data = y_data.float()
# print('标签:',y_data)
4.搭建模型
class LogisticRegression(nn.Module):
def __init__(self):
super(LogisticRegression,self).__init__()
self.lr = nn.Linear(2,1) #定义一个输入神经元2个,输出神经元1个的全连接层
self.sm = nn.Sigmoid() #sigmoid激活函数
#定义自己的前向传播方式
def forward(self,x):
lr_out = self.lr(x)
out = self.sm(lr_out)
return out
5.训练逻辑回归模型 实例化对象
logistic_model = LogisticRegression().cuda()
# 或者:
# if torch.cuda.is_available():
# logistic_model.cuda()
6.定义损失函数和优化器
criterion = nn.BCELoss() #损失函数为BCE损失函数
# 优化方法选用随机梯度下降,学习率为0.001
optimizer = torch.optim.SGD(logistic_model.parameters() , lr=1e-3,momentum=0.9)
7.训练过程
for epoch in range(10000):
if torch.cuda.is_available():
x = x_data.cuda()
y = y_data.cuda()
else:
x = x_data
y = y_data
out = logistic_model(x)
loss = criterion(out, y)
# print_loss = loss.data.item() #输出损失
mask= out.ge(0.5).float() #计算损失 结果大于0.5的归类为1,结果小于0.5的归类为0
# correct =(mask[:,0] == y).sum() #计算正确预测的样本的个数
# acc = correct.item()/x.size(0) #计算准确精度
optimizer.zero_grad()
loss.backward()
optimizer.step()
#每隔1000轮打印一下当前的误差和精度
if (epoch+1) %1000==0:
print('*'*10)
print('epoch {}'.format(epoch+1)) #训练轮数
print('loss is {:.4f}'.format(loss.data.item()))#误差
print('acc is {:.4f}'.format((mask[:,0] == y).sum().item()/x.size(0) )) #准确度
8.可视化数据
x0 = list(filter(lambda x :x[-1]==0.0,data))
# print(x0)
x1 = list(filter(lambda x :x[-1]==1.0,data))
plot_x0_0=[i[0] for i in x0]
plot_x0_1=[i[1] for i in x0]
plot_x1_0=[i[0] for i in x1]
plot_x1_1=[i[0] for i in x1]
plt.plot(plot_x0_0,plot_x0_1,'ro',label='x0')
plt.plot(plot_x1_0,plot_x1_1,'bo',label='x1')
plt.legend(loc='best')
#获取模型参数
w0,w1 = logistic_model.lr.weight.data[0]
w0 = w0.item()
w1 = w1.item()
b = logistic_model.lr.bias.data[0]
#可视化训练的模型,其实就是一条直线
plot_x = np.arange(30,100,0.1)
plot_x = torch.from_numpy(plot_x)
plot_x =plot_x.float()
plot_y =(-w0*plot_x-b/w1)
plot_x =plot_x.numpy()
plot_y =plot_y.numpy()
plt.plot(plot_x,plot_y)
plt.show()