Pytorch 基础——实现线性回归、逻辑回归和卷积神经网络

线性回归

1 步骤

  1. 构建一个类,叫做 LinearRegression
  2. 在这个类中定义模型
  3. 计算 MSE 均方误差损失函数
  4. 定义优化器
  5. 反向传播
  6. 预测

举个例子,我们有个汽车公司,如果车价格越低低,我们可以卖更多的车。

car_price_np = np.array([3,4,5,6,7,8,9], dtype=np.float32).reshape(-1,1)
car_price_tensor = Variable(torch.from_numpy(car_price_np))

number_of_car_sell_np = np.array([ 7.5, 7, 6.5, 6.0, 5.5, 5.0, 4.5], dtype=np.float32).reshape(-1,1)
number_of_car_sell_tensor = Variable(torch.from_numpy(number_of_car_sell_np))

2 定义线性回归

class LinearRegression(nn.Module):
    def __init__(self, input_size, output_size):
        super(LinearRegression, self).__init__()
        self.linear = nn.Linear(input_size, output_size)

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

3 将网络实例化,定义一些参数

input_dim = 1
output_dim = 1
model = LinearRegression(input_dim, output_dim)
mse = nn.MSELoss()
lr = 0.02
optimizer = torch.optim.SGD(model.parameters(), lr=lr)
loss_list = []
total_iter = 1001

4 拟合数据集

for iteration in range(total_iter):
    optimizer.zero_grad()
    results = model(car_price_tensor)
    loss = mse(results, number_of_car_sell_tensor)
    loss.backward()
    optimizer.step()
    loss_list.append(loss.data)

    if (iteration % 100 == 0):
        print("epoch {}, loss {}".format(iteration, loss.data))

逻辑回归

  • 线性回归对于分类任务表现不好
  • 可以使用逻辑回归进行分类
  • 逻辑回归=线性回归+logistic 函数(softmax)

逻辑回归的步骤,这里使用 MNIST 数据集:

  1. 准备数据集
    • 使用 Mnist
    • 数据需要归一化
    • 需要划分训练集和测试集
    • DataLoader 将 dataset 和 sampler 合并到一起
  2. 建立逻辑回归模型
    • 在 pytorch 中,逻辑回归函数是在损失函数中的
  3. 创建模型
  4. 创建损失函数:交叉熵损失函数,其中有包括 softmax
  5. 创建优化器
  6. 训练模型
  7. 预测

1 加载数据集

train = pd.read_csv("./train.csv", dtype=np.float32)

targets_numpy = train.label.values
features_numpy = train.loc[:, train.columns != "label"].values / 255

features_train, features_test, targets_train, targets_test = train_test_split(
    features_numpy, targets_numpy, test_size = 0.2, random_state = 42
)
featuresTrain = torch.from_numpy(features_train)
targetsTrain = torch.from_numpy(targets_train).type(torch.LongTensor)

featuresTest = torch.from_numpy(features_test)
targetsTest = torch.from_numpy(targets_test).type(torch.LongTensor)

train = torch.utils.data.TensorDataset(featuresTrain, targetsTrain)
test = torch.utils.data.TensorDataset(featuresTest, targetsTest)
train_loader = torch.utils.data.DataLoader(train, batch_size=batch_size, shuffle = True)
test_loader = torch.utils.data.DataLoader(test, batch_size = batch_size, shuffle=False)

网络结构

网络结构其实线性回归一模一样,只有损失函数的区别

class LogisticRegressionModel(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(LogisticRegressionModel, self).__init__()
        self.linear = nn.Linear(input_dim, output_dim)

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

2 定义参数和优化器

batch_size = 100
n_iters = 10000
num_epochs = n_iters / (len(features_train) / batch_size)
num_epochs = int(num_epochs)
input_dim = 28 * 28
output_dim = 10

model = LogisticRegressionModel(input_dim, output_dim).cuda()
error = nn.CrossEntropyLoss().cuda()
learning_rate = 1e-3
optimizer = torch.optim.SGD(model.parameters(), lr = learning_rate)

count = 0
loss_list = []
iteration_list = []

3 训练模型

# train the model
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):

        model.train()
        train = Variable(images.view(-1, 28 * 28)).cuda()
        labels = Variable(labels).cuda()

        optimizer.zero_grad()
        output = model(train)
        loss = error(output, labels)
        loss.backward()
        optimizer.step()

        count += 1

        if count % 50 == 0:
            model.eval()
            correct = 0
            total = 0
            
            for images, labels in test_loader:
                test = Variable(images.view(-1, 28 * 28)).cuda()
                output = model(test)
                predicted = torch.max(output.cpu().data, 1)[1]
                total += len(labels)

                correct += (predicted == labels).sum()
            accuracy = 100 * correct / float(total)

            loss_list.append(loss.data)
            iteration_list.append(count)
        if count % 500 == 0:
            print("Iteration: {:.4f}, Loss: {:.4f}, Accuracy: {:.2f}%".format(count, loss.cpu().data, accuracy))

训练完成后在验证集上的精度有 85%。

神经网络

  1. 当问题的变复杂时,逻辑回归的精度就会下降,因此需要提升模型的复杂度
  2. 需要在网络中增加一些非线性的函数
  3. 使用 pytorch 构建神经网络的步骤
    1. 导入库
    2. 准备数据集 Dataset 和 DataLoader
    3. 构建模型
    4. 实例化模型和损失函数,优化器
    5. 训练和预测

1 构建模型

class ANNModel(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(ANNModel, self).__init__()

        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.relu1 = nn.ReLU()

        self.fc2 = nn.Linear(hidden_dim, hidden_dim)
        self.tanh2 = nn.Tanh()

        self.fc3 = nn.Linear(hidden_dim, hidden_dim)
        self.elu3 = nn.ELU()

        self.fc4 = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        x = self.relu1(self.fc1(x))
        x = self.tanh2(self.fc2(x))
        x = self.elu3(self.fc3(x))
        x = self.fc4(x)
        return x

2 实例化与参数

inpud_dim = 28 * 28
output_dim = 10
hidden_dim = 100
cuda = True
model = ANNModel(input_dim, hidden_dim, output_dim)

error = nn.CrossEntropyLoss()
if cuda:
    model = model.cuda()
    error = error.cuda()
lr = 1e-2
optimizer = torch.optim.SGD(model.parameters(), lr = lr)

count = 0
loss_list = []
iteration_list = []
accuracy_list = []

3 训练

# model training
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        model.train()
        train = Variable(images.view(-1, 28 * 28))
        labels = Variable(labels)
        if cuda:
            train = train.cuda()
            labels = labels.cuda()

        optimizer.zero_grad()
        outputs = model(train)
        loss = error(outputs, labels)
        loss.backward()
        optimizer.step()
        count += 1

        if count % 50 == 0:
            model.eval()
            correct = 0
            total = 0
            for images, labels in test_loader:
                test = Variable(images.view(-1, 28 * 28))
                if cuda:
                    test = test.cuda()
                outputs = model(test)
                predicted = torch.max(outputs.data, 1)[1]
                total += len(labels)
                correct += (predicted.cpu() == labels).sum()
            accuracy = 100 * correct / float(total)

            loss_list.append(loss.data)
            iteration_list.append(count)
            accuracy_list.append(accuracy)
            if count % 500 == 0:
                # Print Loss
                print('Iteration: {}  Loss: {:.4f}  Accuracy: {:.2f}%'.format(count, loss.data.item(), accuracy))

经过训练以后,在验证集上的精度达到了 95%,可见模型中的非线性是很重要的。

4 批归一化层

实测,在模型中加入批归一化层,可以加快模型的训练,并且得到效果更好的模型,将模型结构定义如下,最后达到了 97% 的精度。

class ANNModel(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(ANNModel, self).__init__()

        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.bn1 = nn.BatchNorm1d(hidden_dim)
        self.relu1 = nn.ReLU()

        self.fc2 = nn.Linear(hidden_dim, hidden_dim)
        self.bn2 = nn.BatchNorm1d(hidden_dim)
        self.tanh2 = nn.Tanh()

        self.fc3 = nn.Linear(hidden_dim, hidden_dim)
        self.bn3 = nn.BatchNorm1d(hidden_dim)
        self.elu3 = nn.ELU()

        self.fc4 = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        x = self.relu1(self.bn1(self.fc1(x)))
        x = self.tanh2(self.bn2(self.fc2(x)))
        x = self.elu3(self.bn3(self.fc3(x)))
        x = self.fc4(x)
        return x

CNN

  • CNN 在图像分类上表现会很好
  • CNN 的步骤
    • 数据集
    • 卷积层
    • 池化层
    • Flattening:将特征图平铺,变成一个长向量
    • 全连接来做分类
  • 其余步骤与传统的网络一样

1 模型定义

加上了 BN 层可以让网络训练更快,且得到更好的结果

class CNNModel(nn.Module):
    def __init__(self):
        super(CNNModel, self).__init__()

        self.conv1 = nn.Conv2d(in_channels=1, out_channels=16, kernel_size=3,
                               stride=1)
        self.bn1 = nn.BatchNorm2d(16)
        self.relu1 = nn.ReLU()
        self.maxpool1 = nn.MaxPool2d(kernel_size=2)

        self.conv2 = nn.Conv2d(in_channels=16, out_channels=32, kernel_size=3,
                               stride=1)
        self.bn2 = nn.BatchNorm2d(32)
        self.relu2 = nn.ReLU()
        self.maxpool2 = nn.MaxPool2d(kernel_size=2)

        self.fc = nn.Linear(32 * 5 * 5, 10)

    def forward(self, x):
        x = self.conv1(x)
        x = self.bn1(x)
        x = self.relu1(x)
        x = self.maxpool1(x)
        
        x = self.conv2(x)
        x = self.bn2(x)
        x = self.relu2(x)
        x = self.maxpool2(x)

        x = self.fc(x.view(x.shape[0], -1))
        return x

2 实例化与参数

model = CNNModel()
error = nn.CrossEntropyLoss()
if cuda:
    model = model.cuda()
    error = error.cuda()
lr = 1e-1
optimizer = torch.optim.SGD(model.parameters(), lr=lr)
count = 0
loss_list = []
iteration_list = []
accuracy_list = []

3 模型训练

# model training
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        model.train()
        train = Variable(images.view(batch_size, 1, 28, 28))
        labels = Variable(labels)
        if cuda:
            train = train.cuda()
            labels = labels.cuda()

        optimizer.zero_grad()
        outputs = model(train)
        loss = error(outputs, labels)
        loss.backward()
        optimizer.step()
        count += 1

        if count % 50 == 0:
            model.eval()
            correct = 0
            total = 0
            for images, labels in test_loader:
                test = Variable(images.view(batch_size, 1, 28, 28))
                if cuda:
                    test = test.cuda()
                outputs = model(test)
                predicted = torch.max(outputs.data, 1)[1]
                total += len(labels)
                correct += (predicted.cpu() == labels).sum()
            accuracy = 100 * correct / float(total)

            loss_list.append(loss.data)
            iteration_list.append(count)
            accuracy_list.append(accuracy)
            if count % 500 == 0:
                # Print Loss
                print('Iteration: {}  Loss: {:.4f}  Accuracy: {:.2f}%'.format(count, loss.data.item(), accuracy))

通过卷积神经网络,可以达到 98.7% 的精度!

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
下面是一个使用 PyTorch 卷积神经网络进行回归预测的简单示例代码: ```python import torch import torch.nn as nn import torch.optim as optim import numpy as np # 定义一个卷积神经网络模型 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 6, 5) self.pool = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(6, 16, 5) self.fc1 = nn.Linear(16 * 4 * 4, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 1) def forward(self, x): x = self.pool(nn.functional.relu(self.conv1(x))) x = self.pool(nn.functional.relu(self.conv2(x))) x = x.view(-1, 16 * 4 * 4) x = nn.functional.relu(self.fc1(x)) x = nn.functional.relu(self.fc2(x)) x = self.fc3(x) return x # 准备数据 x_train = np.random.rand(100, 1, 28, 28) y_train = np.random.rand(100, 1) # 转换为张量 x_train = torch.from_numpy(x_train).float() y_train = torch.from_numpy(y_train).float() # 定义模型、损失函数和优化器 model = Net() criterion = nn.MSELoss() optimizer = optim.SGD(model.parameters(), lr=0.01) # 训练模型 for epoch in range(100): optimizer.zero_grad() output = model(x_train) loss = criterion(output, y_train) loss.backward() optimizer.step() print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, 100, loss.item())) # 使用训练好的模型进行预测 x_test = np.random.rand(10, 1, 28, 28) x_test = torch.from_numpy(x_test).float() y_pred = model(x_test) print(y_pred) ``` 在这个例子中,我们定义了一个包含两个卷积层和三个全连接层的卷积神经网络模型。我们使用随机生成的数据进行训练,并使用均方误差损失函数和随机梯度下降优化器进行训练。最后,我们使用训练好的模型进行预测。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值