赞
踩
目录
- #导包
- import torch
- from torch import nn
- import matplotlib.pyplot as plt
- # %matplotlib inline
- import numpy as np
- from torch.distributions import MultivariateNormal
- # 设置两组不同的均值向量和协方差矩阵
- # torch.eye()主要是为了生成对角线全是1,其余部分全0的二维数组
- mu1 = -3 * torch.ones(2)
- mu2 = 3 * torch.ones(2)
- sigma1 = torch.eye(2) * 0.5
- sigma2 = torch.eye(2) * 2
- # 各从两个多元高斯分布中生成100个样本
- # 此处定义的多元高斯是二维的
- m1 = MultivariateNormal(mu1, sigma1)
- m2 = MultivariateNormal(mu2, sigma2)
- x1 = m1.sample((100,))
- x2 = m2.sample((100,))
-
- #设置正负样本的标签
- y = torch.zeros((200, 1))
- y[100:] = 1
-
- # 组合、打乱样本
- x = torch.cat([x1, x2], dim=0)
- # np.random.permutation():1、产生一个随机序列 2、对一个随机序列x进行随机排序 3、如果x是一个多维数组,它只会按照第一个索引洗牌
- idx = np.random.permutation(len(x))
- x = x[idx]
- y = y[idx]
-
- # # 绘制样本
- plt.scatter(x1.numpy()[:,0], x1.numpy()[:,1])
- plt.scatter(x2.numpy()[:,0], x2.numpy()[:,1])
- plt.show()
从图中可以看出右上角的簇样本分布稀疏,而左下角分布紧凑。可以自行调整9-10行代码的参数,观察其变化。
- # 线性方程
- # D_in为输入的特征数,D_out为输出的特征数
- D_in, D_out = 2, 1
- linear = nn.Linear(D_in, D_out, bias=True)
- output = linear(x)
-
- print(x.shape, linear.weight.shape, linear.bias.shape, output.shape)
-
- def my_linear(x, w, b):
- return torch.mm(x, w.t()) + b
-
- torch.sum((output - my_linear(x, linear.weight, linear.bias)))
- # 激活函数
- sigmoid = nn.Sigmoid()
- scores = sigmoid(output)
-
- def my_sigmoid(x):
- x = 1/(1 + torch.exp(-x))
- return x
-
- # 通过PyTorch验证我们的试验结果
- torch.sum(scores - my_sigmoid(output))
-
- # 损失函数
- # Logistic回归使用交叉熵作为损失函数
- loss = nn.BCELoss()
- loss(scores, y)
-
- # 下面自定义了二值交叉熵函数,将my_loss和PyTorch的BCELoss进行比较
- def my_loss(x, y):
- loss = - torch.mean(torch.log(x) * y + torch.log(1 - x) * (1 - y))
- return loss
-
- loss(scores, y) - my_loss(my_sigmoid(output), y)
以上是我们使用的torch.nn包中的线性模型nn.Linear、激活函数,损失函数,它们都继承自nn.Module类。而在PyTorch中,我们继承nn.Module来构建我们自己的模型。接下来我们用nn.Module来实现Logistic回归。
- import torch.nn as nn
-
- class LogisticRegression(nn.Module):
- def __init__(self, D_in):
- super(LogisticRegression, self).__init__()
- self.linear = nn.Linear(D_in, 1)
- self.sigmoid = nn.Sigmoid()
-
- # forward方法是必须被子类覆写的,在forward内部应当定义每次调用模型时执行的计算
- def forward(self, x):
- x = self.linear(x)
- x = self.sigmoid(x)
- return x
- #nn.Module类的主要作用就是接收Tensor然后计算并返回结果
- lr_model = LogisticRegression(2)
- loss = nn.BCELoss()
- # print(loss(lr_model(x), y))
-
- # 优化算法
- '''
- Logistic回归通常采用梯度下降法优化目标函数。
- PyTorch的torch.optim包实现了大多数常用算法
- '''
- from torch import optim
-
- optimizer = optim.SGD(lr_model.parameters(), lr=0.03)
- '''
- 构建完优化器,就可以迭代地对模型进行训练,有两个步骤:
- 1、调用损失函数的backward方法计算模型的梯度
- 2、调用优化器的step方法更新模型的参数
- 需要注意的是,应当提前调用优化器zero_grad方法清空参数的梯度
- '''
-
- batch_size = 10
- iters = 10
- # for input, target in dataset:
- for _ in range(iters):
- for i in range(int(len(x)/batch_size)):
- input = x[i*batch_size:(i+1)*batch_size]
- target = y[i*batch_size:(i+1)*batch_size]
- optimizer.zero_grad()
- output = lr_model(input)
- l = loss(output, target)
- l.backward()
- optimizer.step()
-
- # 优化算法
- '''
- Logistic回归模型的判决边界在高维空间的一个超平面,而我们的数据集是二维,所以判决边界只是平面内的一条直线,
- 在线的一侧被预测为正类,另一侧则被预测为父类。
- draw_decision_boundary函数接收线性模型的参数w和b,以及数据集x。
- 绘制判决边界只需要计算一些数据在线模型的映射值,然后调用plt.plot绘制线条即可。
- '''
-
- pred_neg = (output <= 0.5).view(-1)
- pred_pos = (output > 0.5).view(-1)
- plt.scatter(x[pred_neg, 0], x[pred_neg, 1])
- plt.scatter(x[pred_neg, 0], x[pred_pos, 1])
-
- w = lr_model.linear.weight[0]
- b = lr_model.linear.bias[0]
-
- def draw_decision_boundary(w, b, x0):
- x1 = (-b - w[0] * x0) / w[1]
- plt.plot(x0.detach().numpy(), x1.detach().numpy(), 'r')
- plt.show()
-
- draw_decision_boundary(w, b, torch.linspace(x.min(), x.max(), 50))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。