白板推导系列Pytorch-逻辑回归

白板推导系列Pytorch-逻辑回归

逻辑回归的从零实现

导入需要的包

import torch
import matplotlib.pyplot as plt
import torch.nn as nn
from torch.autograd import Variable

生成数据集

def create_dataset(n_samples=1000):
    n_data = torch.ones(n_samples//2, 2)
    x0 = torch.normal(2 * n_data, 1)  # 生成均值为2.标准差为1的随机数组成的矩阵 shape=(100, 2)
    y0 = torch.zeros(n_samples//2)
    x1 = torch.normal(-2 * n_data, 1)  # 生成均值为-2.标准差为1的随机数组成的矩阵 shape=(100, 2)
    y1 = torch.ones(n_samples//2)
    x=torch.cat((x0,x1),0).type(torch.FloatTensor)
    y=torch.cat((y0,y1),0).type(torch.FloatTensor)
    return x,y

定义Sigmoid和交叉熵损失函数

def sigmoid(x):
    return 1/(1+torch.exp(-x))

def loss(y,y_pred):
    return -(y*torch.log(y_pred)+(1-y)*torch.log(1-y_pred))

定义模型

class LogisticRegression:
    def __init__(self,lr=1e-4,batch_size=64,n_epoch=100) -> None:
        self.lr = lr
        self.batch_size = batch_size
        self.n_epoch = n_epoch
        
	# 训练
    def fit(self,X_data,y_data):
        self.weight = torch.normal(2,0.01,size=(X_data.shape[1],),requires_grad=True)
        dataset = Data.TensorDataset(X_data,y_data)
        train_iter = Data.DataLoader(dataset,batch_size=self.batch_size)
        history = {
            'loss':[],
            'acc':[]
        }
        for epoch in range(self.n_epoch):
            for X,y in train_iter:
                y_pred = torch.matmul(X,self.weight)
                y_pred = sigmoid(y_pred)
                l = loss(y,y_pred).sum()
                if l>0:
                    l.backward()
                    self.weight.data -= self.weight.grad.data*self.lr
                    self.weight.grad.data.zero_()
            print('epoch {}'.format(epoch+1),end='  ')
            l,acc = self.score(X_data,y_data)
            history['loss'].append(l)
            history['acc'].append(acc)
        return history
	# 评估
    def score(self,X_data,y_data):
        with torch.no_grad():
            y_pred = torch.matmul(X_data,self.weight)
            y_pred = sigmoid(y_pred)
            all_loss = loss(y_data,y_pred).sum().item()

            mask = (y_pred>=0.5).view(len(y_pred,))
            correct = (mask==y_data).sum().item()
            acc = correct/len(y_pred)
            print("loss is {:.4f}  acc is {:.4f}".format(all_loss,acc))
            return all_loss,acc
	# 预测
    def predict(self,X_data):
        with torch.no_grad():
            y_pred = torch.matmul(X_data,self.weight)
            y_pred = sigmoid(y_pred)
            return (y_pred>=0.5).view(len(y_pred,))

模型训练与评估

X,y = create_dataset(1000)
lr = LogisticRegression()
history = lr.fit(X[:800],y[:800])
lr.score(X[800:],y[800:])

绘制损失曲线和准确率曲线

def plot_history(history,loss=True,acc=True):
    if loss:
        plt.plot(torch.arange(len(history['loss'])),history['loss'])
        plt.show()
    if acc:
        plt.plot(torch.arange(len(history['acc'])),history['acc'])
        plt.show()
        
plot_history(history)

在这里插入图片描述

在这里插入图片描述

逻辑回归的简单实现

导入需要的包

import torch
import matplotlib.pyplot as plt
import torch.nn as nn
from torch.autograd import Variable

生成数据集

def create_dataset(n_samples=1000):
    n_data = torch.ones(n_samples//2, 2)
    x0 = torch.normal(2 * n_data, 1)  # 生成均值为2.标准差为1的随机数组成的矩阵 shape=(100, 2)
    y0 = torch.zeros(n_samples//2)
    x1 = torch.normal(-2 * n_data, 1)  # 生成均值为-2.标准差为1的随机数组成的矩阵 shape=(100, 2)
    y1 = torch.ones(n_samples//2)
    x=torch.cat((x0,x1),0).type(torch.FloatTensor)
    y=torch.cat((y0,y1),0).type(torch.FloatTensor)
    return x,y
X,y = create_dataset(1000)
plt.scatter(X[:,0],X[:,1],c=y)

在这里插入图片描述

定义模型

class LogisticRegression(nn.Module):
    def __init__(self):
        super(LogisticRegression,self).__init__()
        self.lr=nn.Linear(2,1)   #相当于通过线性变换y=x*T(A)+b可以得到对应的各个系数
        self.sm=nn.Sigmoid()   #相当于通过激活函数的变换

    def forward(self, x):
        x=self.lr(x)
        x=self.sm(x)
        return x

定义损失函数和优化器

net = LogisticRegression()
criterion=nn.BCELoss()   #选用BCE损失函数,该损失函数是只用于2分类问题的损失函数
optimizer=torch.optim.SGD(net.parameters(),lr=1e-3,momentum=0.9)  #采用随机梯度下降的方法

定义训练过程

def train(net,X_data,y_data,batch_size,epoch):
    if torch.cuda.is_available():
        net = net.cuda()
        X_data=Variable(X_data).cuda()
        y_data=Variable(y_data).cuda()
    else:
        X_data=Variable(X_data)
        y_data=Variable(y_data)
    # 创建数据加载器
    dataset = Data.TensorDataset(X_data,y_data)
    train_iter = Data.DataLoader(dataset,batch_size=batch_size)
    net.train()
    history = {
        "loss":[],
        "acc":[]
    }
    #开始训练
    for i in range(epoch):
        all_loss = 0
        for X,y in train_iter:
            #根据逻辑回归模型拟合出的y值
            y_pred = net(X)  
            #计算损失函数
            loss = criterion(y_pred,y.view(len(y),-1))
            #梯度清零
            optimizer.zero_grad()
            #反向传播
            loss.backward()
            #梯度更新
            optimizer.step()
            all_loss += loss.data.item()
        print('epoch {}'.format(i+1),end='  ')
        loss,acc = evaluate(net,X_data,y_data,batch_size)
        history['loss'].append(loss)
        history['acc'].append(acc)
    return history

定义模型评估

def evaluate(net,X_data,y_data,batch_size):
    if torch.cuda.is_available():
        net = net.cuda()
        X_data=Variable(X_data).cuda()
        y_data=Variable(y_data).cuda()
    else:
        X_data=Variable(X_data)
        y_data=Variable(y_data)
    # 创建数据加载器
    dataset = Data.TensorDataset(X_data,y_data)
    test_iter = Data.DataLoader(dataset,batch_size=batch_size)
    net.eval()
    correct = 0
    all_loss = 0
    for X,y in test_iter:
        y_pred = net(X)
        loss = criterion(y_pred,y.view(len(y),-1))
        correct += ((y_pred>=0.5).view(len(y_pred),)==y).sum().item()
        all_loss += loss
    acc = correct/len(y_data)
    print("loss is {:.4f}  acc is {:.4f}".format(all_loss,acc))
    return all_loss,acc

训练

history = train(net,X[:800],y[:800],256,100)
plot_history(history)

在这里插入图片描述

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤独腹地

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值