import torch
from torch.autograd import Variable#Variable就是一个存放会变化值的地理位置,就像一个装鸡蛋的篮子,鸡蛋数会不断发生变化
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
torch.manual_seed(2017)#设计随机种子
#从data.txt中读入点
with open('C:\\Users\\songsaishuang\\Desktop\\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))#filter(判断过滤函数,数据),最后一列为0的过滤出来,选择第一类的点
x1=list(filter(lambda x:x[-1]==1.0,data))#选择第二类的点
plot_x0=[i[0] for i in x0]
plot_y0=[i[1] for i in x0]
plot_x1=[i[0] for i in x1]
plot_y1=[i[1] for i in x1]
plt.plot(plot_x0,plot_y0,'ro',label='x_0')
plt.plot(plot_x1,plot_y1,'ro',label='x_1')
plt.legend(loc='best')#设置图例位置
#转换成tensor格式
np_data=np.array(data,dtype='float32')#转换为numpy array
x_data=torch.from_numpy(np_data[:,0:2])#转换成Tensor,大小是[100,2]data[第几列,第几行:]取第一列和第二列的数据,含左不含右
y_data=torch.from_numpy(np_data[:,-1]).unsqueeze(1)#转换成tensor,大小是[100,1]
#定义sigmoid函数
def sigmoid(x):
return 1/(1+np.exp(-x))
#画出sigmoid的图像
plot_x=np.arange(-10,10.01,0.01)
plot_y=sigmoid(plot_x)
plt.plot(plot_x,plot_y,'r')
x_data=Variable(x_data)
y_data=Variable(y_data)
import torch.nn.functional as F
#定义logistic回归模型
w=Variable(torch,randn(2,1),requires_grad=True)#随机数2行一列
b=Variable(torch,zeros(1),requires_grad=True)
def logistic_regression(x):
return F.sigmoid(torch.mm(x,w)+b)#mm(x,w)是x乘于w
#画出参数更新前的结果
w0=w[0].data[0]
w1=w[1].data[0]
b0=b.data[0]
plot_x=np.arange(0.2,1,0.01)
plot_y=(-w0*plot_x-b0)/w1
plt.plot(plot_x,plot_y,'g',label='cutting line')
plt.plot(plot_x0,plot_y0,'ro',label='x_0')
plt.plot(plot_x1,plot_y1,'bo',label='x_1')
plt.legend(loc='best')
#计算loss函数
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
y_pred=logistic_regression(x_data)
loss=binary_loss(y_pred,y_data)
print(loss)
#自动求导并更新参数
loss.backward()
w.data=w.data-0.1*w.grad.data
b.data=b.data-0.1*b.grad.data
#算出一次更新后的loss
y_pred=logistic_regression(x_data)
loss=binary_loss(y_pred,y_data)
print(loss)
#使用torch.optim更新参数
from torch import nn
w=nn.Parameter(torch.randn(2,1))
b=nn.Parameter(torch.zeros(1))
def logistic_regression(x):
return F.sigmoid(torch.mm(x,w)+b)
optimizer=torch.optim.SGD([w,b],lr=1.)
#进行1000次更新
import time
start=time.time()
for e in range(1000):
#前向传播
y_pred=logistic_regression(x_data)
loss=binary_loss(y_pred,y_data)
#反向传播
optimizer.zero_grad()#使用优化器将梯度清零
loss.backward()
optimizer.step()#更新参数
#计算正确率
mask=y_pred.ge(0.5).float()
acc=(mask==y_data).sum().data[0]/y_data.shape[0]#y_data.shape[0]返回行数
if(e+1)%200==0:
print('epoch:{},Loss:{:.5f},Acc:{:.5f}'.format(e+1,loss.data[0],acc))
during=time.time()-start
print()
print('During Time:{:.3f} s'.format(during))
#画出参数更新前的结果
w0=w[0].data[0]
w1=w[1].data[0]
b0=b.data[0]
plot_x=np.arange(0.2,1,0.01)
plot_y=(-w0*plot_x-b0)/w1
plt.plot(plot_x,plot_y,'g',label='cutting line')
plt.plot(plot_x0,plot_y0,'ro',label='x_0')
plt.plot(plot_x1,plot_y1,'bo',label='x_1')
plt.legend(loc='best')
'''还可直接使用自带的loss
区别在于:criterion=nn.BCEWithLogitsLoss()#将sigmoid和loss写在一层
def logistic_regression(x):
return torch.mm(x,w)+b