Linear Regression、Logistic Regression、激励函数activation function(relu,sigmoid, tanh, softplus)

1.5.2.Linear Regression
1.5.2.1.Linear Regression
1.5.2.1.1.案例1
1.5.2.1.2.案例2
1.5.2.1.3.案例3源码(带有保存模型)
1.5.2.2.Logistic Regression
1.5.2.2.1.案例1
1.5.2.2.2.更深更宽的网络
1.5.2.2.3.逻辑回归案例
1.5.2.3.Classification
1.5.2.4.激励函数activation function(relu,sigmoid, tanh, softplus)

1.5.2.Linear Regression

以下转自:

https://blog.csdn.net/caichao08/article/details/78993893
https://blog.csdn.net/weixin_42587745/article/details/90346126
https://ptorch.com/news/6.html
https://www.jb51.net/article/140557.htm
1.5.2.1.Linear Regression

对于线性回归,即给出一系列的点,找一条直线,使得这条直线与这些点的距离之和最小。
在这里插入图片描述
上图就简单地描绘出了线性回归的基本原理,接下来我们来重点讲讲如何用pytorch写一个简单的线性回归。

接下来,使用torch.from_numpy()和numpy函数即可进行相互转换:

x = torch.from_numpy(x)
y = torch.from_numpy(y)
1.5.2.1.1.案例1

使用PyTorch定义线性回归模型一般分以下几步:
1.设计网络架构
2.构建损失函数(loss)和优化器(optimizer)
3.训练(包括前馈(forward)、反向传播(backward)、更新模型参数(update))

# -*- coding: UTF-8 -*-

import torch
from torch.autograd import Variable

# train data
x_data = Variable(torch.Tensor([[1.0],[2.0],[3.0]]))
y_data = Variable(torch.Tensor([[2.0],[4.0],[6.0]]))

class Model(torch.nn.Module):
    def __init__(self):
        super(Model,self).__init__()
        self.linear = torch.nn.Linear(1,1)  #One in and one out

    def forward(self, x):
        y_pred = self.linear(x)
        return y_pred


# our model
model = Model()

criterion = torch.nn.MSELoss(size_average=False)         # Defined loss function
optimizer = torch.optim.SGD(model.parameters(),lr=0.01)  # Defined optimizer

# Training: forward,loss,backward,step
# Training loop
for epoch in range(50):
    # Forward pass
    y_pred = model(x_data)

    # Compute loss
    loss = criterion(y_pred, y_data)
    print(epoch,'次循环:', loss.data.numpy())

    # Zero gradients
    optimizer.zero_grad()
    # perform backward pass
    loss.backward()
    # update weights
    optimizer.step()


# After training
hour_var = Variable(torch.Tensor([[4.0]]))
print("predict (after training)", 4, model.forward(hour_var).data.numpy())

迭代十次打印结果:

0 次循环: 128.36353
1 次循环: 57.22348
2 次循环: 25.55281
3 次循环: 11.452799
4 次循环: 5.1747613
5 次循环: 2.3788614
6 次循环: 1.1331253
7 次循环: 0.57749355
8 次循环: 0.32909214
9 次循环: 0.2174757

loss还在继续下降,此时输入4得到的结果还不是预测的很准
当迭代次数设置为50时:

10 次循环: 0.16676745
11 次循环: 0.14318845
12 次循环: 0.13170049
13 次循环: 0.12560984
14 次循环: 0.12193605
15 次循环: 0.11935152
16 次循环: 0.117265806
17 次循环: 0.11541578
18 次循环: 0.11368369
19 次循环: 0.11201717
20 次循环: 0.11039279
21 次循环: 0.108799875
22 次循环: 0.10723348
23 次循环: 0.105691046
24 次循环: 0.10417137
25 次循环: 0.10267406
26 次循环: 0.10119824
27 次循环: 0.09974393
28 次循环: 0.09831043
29 次循环: 0.0968976
30 次循环: 0.09550497
31 次循环: 0.09413239
32 次循环: 0.09277948
33 次循环: 0.09144618
34 次循环: 0.0901321
35 次循环: 0.08883653
36 次循环: 0.08755979
37 次循环: 0.08630159
38 次循环: 0.085061245
39 次循环: 0.08383879
40 次循环: 0.082633875
41 次循环: 0.08144614
42 次循环: 0.08027585
43 次循环: 0.07912208
44 次循环: 0.07798502
45 次循环: 0.07686419
46 次循环: 0.07575947
47 次循环: 0.07467067
48 次循环: 0.073597685
49 次循环: 0.07253992
predict (after training) 4 [[7.690391]]

此时,函数已经拟合比较好了

torch.nn.Linear(1,1),只需要知道输入和输出维度,里面的参数矩阵是随机初始化的(具体是不是随机的还是按照一定约束条件初始化的我不确定),所有每次计算loss会下降到不同的位置(模型的参数更新从而也不同),导致结果不一样。

1.5.2.1.2.案例2

以下转自:https://blog.csdn.net/caichao08/article/details/78993893

首先第一步是产生训练的数据,这里我们采用scikit工具箱来完成。

# -*- coding: UTF-8 -*-

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_regression
import torch
import torch.nn as nn
from torch.autograd import Variable

# n_samples表示样本数量, n_features表示输入参数个数, noise代表噪声, coef选择是否输出系数
# 当n_features = 1 时,可以进行可视化
X, y, coef =make_regression(n_samples=1000, n_features=1,noise=10, coef=True)
plt.scatter(X, y,  color='green')
plt.plot(X, X*coef, color='red',linewidth=3)
plt.xticks(())
plt.yticks(())
plt.show()

print(coef)
print(np.shape(X))
print(np.shape(y))

输出结果:

84.20925934904598
(1000, 1)
(1000,)

下一步是建立一个模型

# 首先将数据转换成tensor变量
# 上面的make_regression产生的是double型数据, 直接导入到tensor里面会跑不通, 这里把它们转成float32型的变量
X = X.astype('float32')
y = y.astype('float32')

print(np.size(X))
print(np.shape(X))
print(np.shape(y))

# 下面的这一步非常的关键, pytorch里面只支持(n, 1)这种类型的matric,而不支持这种(n,)类似的scaler或vector类型的变量
y = np.reshape(y, (np.size(X), 1))
# 下面是将numpy转换成Tensor,使用torch.from_numpy()和numpy函数即可进行相互转换
train_x = torch.from_numpy(X)
train_y = torch.from_numpy(y)


# 再定义一个模型,一般用类的形式来产生
# 这里的nn.Module是被继承了,nn.Module里面包含了很多需要的模块
class linear_regression(nn.Module):
    """
    linear regression module
    """

    def __init__(self):
        super(linear_regression, self).__init__()
        # 定义Linear 函数只有一个输入一个输出,这里的nn.Linear表示的是 y=w*x+b,里面的两个参数都是1,表示的是x是1维,y也是1维。
        self.linear = nn.Linear(1, 1)

    def forward(self, x):
        out = self.linear(x)
        return out


model = linear_regression()
print(model)
print(train_x.size())
print(train_y.size())
print(type(train_x))

输出结果:

1000
(1000, 1)
(1000,)
linear_regression(
  (linear): Linear(in_features=1, out_features=1, bias=True)
)
torch.Size([1000, 1])
torch.Size([1000, 1])
<class 'torch.Tensor'>

接着对模型的未知参数进行求解

# 紧接着需要定义loss和optimize了
# 利用最小二乘来定义损失
# 学习率,当学习率很小的时候,得循环很多次才能得到比较好的结果,如果是le-3,下面的num_epoch得1900次差不多才能得到比较好的效果
learning_rate = 1e-2   

# 这里使用的是最小二乘loss,之后我们做分类问题更多的使用的是cross entropy loss,交叉熵。优化函数使用的是随机梯度下降,注意需要将model的参数model.parameters()传进去让这个函数知道他要优化的参数是哪些。
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

# SGD的第一参数传入的是模型要优化的参数, 第二个表示的是学习率
# 开始训练
num_epoch = 200

for epoch in range(num_epoch):
    # 将数据转换成tensor变量,这样可以自动求导
    inputs = Variable(train_x)
    targets = Variable(train_y)
    # # 前向 + 后向 + 优化
    optimizer.zero_grad()
    outputs = model(inputs)
    loss = criterion(outputs, targets)
    loss.backward()
    optimizer.step()

if (epoch+1) % 20 == 0:
        print("loss:" + {loss.item()})
        #print(f'Epoch[{epoch+1}/{num_epochs}], loss: {loss.item():.6f}')

只要learning_rate选的好,这里基本上一步就能得出正确结果了

再看看预测的结果

# 下面来用数据做预测
# 特别注意的是需要用model.eval(),让model变成测试模式,这主要是对dropout和batch,  normalization的操作在训练和测试的时候是不一样的。
model.eval()
# model只支持tensor类型的变量, 所以对model的输入要进行转换, 而画图则要转化成numpy类型
predicts = model(Variable(train_x)).data.numpy()
plt.figure()
plt.plot(X, y, 'go', label=u'original data')
plt.plot(X, coef*X, 'b', label=u'ground truth')
plt.plot(X, predicts, 'r', label=u'predicted data')
plt.legend()
plt.show()

从下面的结果图上来看还是很准的
在这里插入图片描述

1.5.2.1.3.案例3源码(带有保存模型)
# -*- coding: UTF-8 -*-

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

x_train = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168],
                    [9.779], [6.182], [7.59], [2.167], [7.042],
                    [10.791], [5.313], [7.997], [3.1]], dtype=np.float32)

y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573],
                    [3.366], [2.596], [2.53], [1.221], [2.827],
                    [3.465], [1.65], [2.904], [1.3]], dtype=np.float32)


x_train = torch.from_numpy(x_train)

y_train = torch.from_numpy(y_train)


# Linear Regression Model
class linearRegression(nn.Module):
    def __init__(self):
        super(linearRegression, self).__init__()
        self.linear = nn.Linear(1, 1)  # input and output is 1 dimension

    def forward(self, x):
        out = self.linear(x)
        return out


model = linearRegression()
# 定义loss和优化函数
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=1e-4)

# 开始训练
num_epochs = 2000
for epoch in range(num_epochs):
    inputs = x_train
    target = y_train

    # forward
    out = model(inputs)
    loss = criterion(out, target)
    # backward
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if (epoch+1) % 20 == 0:
        print(f'Epoch[{epoch+1}/{num_epochs}], loss: {loss.item():.6f}')

model.eval()
with torch.no_grad():
    predict = model(x_train)
predict = predict.data.numpy()

fig = plt.figure(figsize=(10, 5))
plt.plot(x_train.numpy(), y_train.numpy(), 'ro', label='Original data')
plt.plot(x_train.numpy(), predict, label='Fitting Line')
# 显示图例
plt.legend()
plt.show()

# 保存模型
torch.save(model.state_dict(), './linear.pth')

运行结果:

Epoch[20/2000], loss: 16.022251
Epoch[40/2000], loss: 11.373667
Epoch[60/2000], loss: 8.088304
Epoch[80/2000], loss: 5.766390
Epoch[100/2000], loss: 4.125387
Epoch[120/2000], loss: 2.965617
Epoch[140/2000], loss: 2.145954
Epoch[160/2000], loss: 1.566661
Epoch[180/2000], loss: 1.157250
Epoch[200/2000], loss: 0.867900
Epoch[220/2000], loss: 0.663402
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Epoch[1960/2000], loss: 0.170428
Epoch[1980/2000], loss: 0.170426
Epoch[2000/2000], loss: 0.170425
1.5.2.2.Logistic Regression

以下参考:https://www.jb51.net/article/140557.htm
http://blog.csdn.net/m0_37306360
线性回归是解决回归问题的,逻辑回归和线性回归很像,但是它是解决分类问题的(一般二分类问题:0 or 1)。也可以多分类问题(用softmax可以实现)。

使用pytorch实现逻辑回归的基本过程和线性回归差不多,但是有以下几个区别:
在这里插入图片描述
以下为sigmoid函数:
在这里插入图片描述

在逻辑回归中,我们预测如果当输出大于0.5时,y=1;否则y=0。
损失函数一般采用交叉熵loss:
在这里插入图片描述

1.5.2.2.1.案例1
import torch
from torch.autograd import Variable

x_data = Variable(torch.Tensor([[0.6], [1.0], [3.5], [4.0]]))
y_data = Variable(torch.Tensor([[0.], [0.], [1.], [1.]]))


class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.linear = torch.nn.Linear(1, 1)  # One in one out
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self, x):
        y_pred = self.sigmoid(self.linear(x))
        return y_pred


# Our model
model = Model()

# Construct loss function and optimizer
criterion = torch.nn.BCELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

# Training loop
for epoch in range(500):
    # Forward pass
    y_pred = model(x_data)

    # Compute loss
    loss = criterion(y_pred, y_data)
    if epoch % 20 == 0:
        print(loss.data.numpy())
        
    # Zero gradients
    optimizer.zero_grad()
    # Backward pass
    loss.backward()
    # update weights
    optimizer.step()
    

# After training
hour_var = Variable(torch.Tensor([[0.5]]))
print("predict (after training)", 0.5, model.forward(hour_var).data[0][0])
hour_var = Variable(torch.Tensor([[7.0]]))
print("predict (after training)", 7.0, model.forward(hour_var).data[0][0])

输出结果为:

2.1419365
1.5513724
1.0856804
0.7997792
0.6584054
0.59043765
0.55404615
0.53147745
0.5154158
0.50267094
0.49175227
0.4819196
0.47278577
0.46413925
0.4558599
0.44787702
0.44014725
0.432643
0.4253458
0.41824245
0.4113233
0.4045803
0.3980071
0.3915978
0.38534725
predict (after training) 0.5 tensor(0.4064)
predict (after training) 7.0 tensor(0.9840)

训练完模型之后,输入新的数据0.5,此时输出小于0.5,则为0类别,输入7输出大于0.5,则为1类别。使用softmax做多分类时,哪个维度的数值大,则为哪个数值所对应位置的类别。

1.5.2.2.2.更深更宽的网络

前面的例子都是浅层输入为一维的网络,如果需要更深更宽的网络,使用pytorch也可以很好的实现,以逻辑回归为例:

当输入x的维度很大时,需要更宽的网络:
在这里插入图片描述
更深的网络:
在这里插入图片描述
采用下面数据集(下载地址:https://github.com/hunkim/PyTorchZeroToAll/tree/master/data)
在这里插入图片描述
输入维度为八:

# -*- coding: UTF-8 -*-

import torch
from torch.autograd import Variable
import numpy as np

xy = np.loadtxt('./data/diabetes.csv', delimiter=',', dtype=np.float32)
x_data = Variable(torch.from_numpy(xy[:, 0:-1]))
y_data = Variable(torch.from_numpy(xy[:, [-1]]))

# print(x_data.data.shape)
# print(y_data.data.shape)


class Model(torch.nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.l1 = torch.nn.Linear(8, 6)
        self.l2 = torch.nn.Linear(6, 4)
        self.l3 = torch.nn.Linear(4, 1)
        self.sigmoid = torch.nn.Sigmoid()

    def forward(self, x):
        x = self.sigmoid(self.l1(x))
        x = self.sigmoid(self.l2(x))
        y_pred = self.sigmoid(self.l3(x))
        return y_pred


# our model
model = Model()

cirterion = torch.nn.BCELoss(size_average=True)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

hour_var = Variable(torch.Tensor([[-0.294118, 0.487437, 0.180328, -0.292929, 0, 0.00149028, -0.53117, -0.0333333]]))
print("(Before training)", model.forward(hour_var).data)

# Training loop
for epoch in range(2000):
    y_pred = model(x_data)
    # y_pred,y_data不能写反(因为损失函数为交叉熵loss)
    loss = cirterion(y_pred, y_data)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    if epoch % 50 == 0:
        print(epoch, loss.data.numpy())


# After training
hour_var = Variable(torch.Tensor([[-0.294118, 0.487437, 0.180328, -0.292929, 0, 0.00149028, -0.53117, -0.0333333]]))
print("predict (after training)", model.forward(hour_var).data.numpy())

结果:

(Before training) tensor([[0.3952]])
0 0.78095376
50 0.7321978
100 0.7009846
150 0.68111795
200 0.668492
250 0.66046023
300 0.6553401
350 0.65206724
400 0.6499692
xxxxxxxxxxxxxxxxxxx
1550 0.6460486
1600 0.6460425
1650 0.64603657
1700 0.6460306
1750 0.64602476
1800 0.6460189
1850 0.6460131
1900 0.6460073
1950 0.6460014
predict (after training) [[0.6534828]]
1.5.2.2.3.逻辑回归案例:
# -*- coding: UTF-8 -*-

import time

import torch
from torch import nn
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

# 定义超参数
batch_size = 64
learning_rate = 1e-3
num_epochs = 100

# 下载训练集 MNIST 手写数字训练集
train_dataset = datasets.FashionMNIST(
    root='../datasets', train=True, transform=transforms.ToTensor(), download=True)

test_dataset = datasets.FashionMNIST(
    root='../datasets', train=False, transform=transforms.ToTensor())

train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)


# 定义 Logistic Regression 模型
class Logistic_Regression(nn.Module):
    def __init__(self, in_dim, n_class):
        super(Logistic_Regression, self).__init__()
        self.logistic = nn.Linear(in_dim, n_class)

    def forward(self, x):
        out = self.logistic(x)
        return out


model = Logistic_Regression(28 * 28, 10)  # 图片大小是28x28
use_gpu = torch.cuda.is_available()  # 判断是否有GPU加速
if use_gpu:
    model = model.cuda()
# 定义loss和optimizer
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

# 开始训练
for epoch in range(num_epochs):
    print('*' * 10)
    print(f'epoch {epoch + 1}')
    since = time.time()
    running_loss = 0.0
    running_acc = 0.0
    model.train()
    for i, data in enumerate(train_loader, 1):
        img, label = data
        img = img.view(img.size(0), -1)  # 将图片展开成 28x28
        if use_gpu:
            img = img.cuda()
            label = label.cuda()
        # 向前传播
        out = model(img)
        loss = criterion(out, label)
        running_loss += loss.item()
        _, pred = torch.max(out, 1)
        running_acc += (pred == label).float().mean()
        # 向后传播
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if i % 300 == 0:
            print(f'[{epoch + 1}/{num_epochs}] Loss: {running_loss / i:.6f}, Acc: {running_acc / i:.6f}')
    print(f'Finish {epoch + 1} epoch, Loss: {running_loss / i:.6f}, Acc: {running_acc / i:.6f}')
    model.eval()
    eval_loss = 0.
    eval_acc = 0.
    for data in test_loader:
        img, label = data
        img = img.view(img.size(0), -1)
        if use_gpu:
            img = img.cuda()
            label = label.cuda()
        with torch.no_grad():
            out = model(img)
            loss = criterion(out, label)
        eval_loss += loss.item()
        _, pred = torch.max(out, 1)
        eval_acc += (pred == label).float().mean()
    print(f'Test Loss: {eval_loss / len(test_loader):.6f}, Acc: {eval_acc / len(test_loader):.6f}')
    print(f'Time:{(time.time() - since):.1f} s')

# 保存模型
torch.save(model.state_dict(), './logstic.pth')
1.5.2.3.Classification

以下参考:https://www.jb51.net/article/139098.htm

1.5.2.4.激励函数activation function

以下参考:https://www.jb51.net/article/139098.htm
Torch的激励函数都在torch.nn.functional中,relu,sigmoid, tanh, softplus都是常用的激励函数。

相关代码:

# -*- coding: UTF-8 -*-

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

x = torch.linspace(-5, 5, 200)
x_variable = Variable(x)  # 将x放入Variable
x_np = x_variable.data.numpy()

# 经过4种不同的激励函数得到的numpy形式的数据结果
y_relu = F.relu(x_variable).data.numpy()
y_sigmoid = torch.sigmoid(x_variable).data.numpy()
y_tanh = torch.tanh(x_variable).data.numpy()
y_softplus = F.softplus(x_variable).data.numpy()

plt.figure(1, figsize=(8, 6))

plt.subplot(221)
plt.plot(x_np, y_relu, c='red', label='relu')
plt.ylim((-1, 5))
plt.legend(loc='best')

plt.subplot(222)
plt.plot(x_np, y_sigmoid, c='red', label='sigmoid')
plt.ylim((-0.2, 1.2))
plt.legend(loc='best')

plt.subplot(223)
plt.plot(x_np, y_tanh, c='red', label='tanh')
plt.ylim((-1.2, 1.2))
plt.legend(loc='best')

plt.subplot(224)
plt.plot(x_np, y_softplus, c='red', label='softplus')
plt.ylim((-0.2, 6))
plt.legend(loc='best')

plt.show()

输出结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值