文章目录

0. BP和MLP1 分类1.0 数据集1.1 网络架构1.2 代码1.3 结果

2 回归2.0 数据集2.1 网络架构2.2 代码2.3 结果

3 代码(可直接食用)

众所周知,sklearn提供了MLP函数。个人认为这个东西虽然蛮好用的——有的时候比你自己写的效果都好,但是,不是长久之计。通过Pytorch能建立自定义程度更高的人工神经网络,往后在网络里面加乱七八糟的东西都很方便(比如GA/PSO求解超参之类的、比如微调模型架构之类的)。本文将不再对MLP的理论基础进行赘述,直接介绍MLP的具体搭建方法。

0. BP和MLP

在做这个之前,我突然想到一个问题

我现在出了一篇 MLP 的文章,要不要再出一个 BP 的?

沉默……

这俩有什么区别啊???

跟某知名大博主讨论了一下,感觉大概是这样的:

我们先明确3个概念:

BP:BP的全称是back propagation(反向传播算法),这并不是一个神经网络。BP神经网络:用了BP算法的神经网络。MLP:多层感知机,也就是我们说的神经网络。

那么我们不难发现,所谓的BP神经网络其实应该是(BP-MLP ) <=> BP神经网络 = BP算法 + MLP(多层感知机)

也就是说,BP 和 MLP 本身是平行的两个概念,不是一件事;它们是 BP 神经网络这个事物的两个不同的方面。

猜测

最开始的时候,神经网络方面的知识还不够丰富,这个时候人们把刚开始的那个简单的结构称作MLP。

随着时间的流逝,人们发现了反向传播算法(BP),这个时候开始强调训练方法了,所以将其相关的神经网络称为BP神经网络。

再往后,因为人们都用BP了,BP不那么新那么火了,这个时候又开始强调模型结构了,就出现了乱七八糟的其他神经网络。

1 分类

1.0 数据集

数据集我采用的是之前接手的一个保险理赔项目。

目标是判断用户是不是来骗保的,给了一大堆特征,这里我就不详细解释是哪些特征了,这篇文章主要负责搭建模型。

归一化之后发现数据还是非常稀疏的,而且看着可能二值化效果会不错,嫌麻烦,不尝试了,就直接拿这个用也没什么大问题。

是一个4分类任务,结果可能没2分类好看,这跟项目的数据也有关,本身数据也比较脏、噪声也比较多,感觉特征与 label 之间的联系也不是特别紧密。不过问题不大,我们的重心还是放在搭网络上。

数据集缺点还包括样本不平衡,确实会影响结果。

data.csv (36221x24)=> 已经包括 label 了

1.1 网络架构

torch 输出的架构如下

一共是4层隐藏层(10->10->10->10)

也尝试过 128->64->16 和一些大的复杂的多层感知机,效果反而没这个好,从混淆矩阵看能发现过拟合了。

1.2 代码

分类任务的相关文件如下

MLP_clf.py 分类模型架构

data.csv 分类数据集

run.py 主函数

utils.py 相关函数和类

run.py

import os

import numpy

import torch

import random

from utils import Config, CLF_Model, REG_Model

from clf_model.MLP_clf import MLP

# 随机数种子确定

seed = 1129

random.seed(seed)

numpy.random.seed(seed)

torch.manual_seed(seed)

torch.cuda.manual_seed(seed)

torch.cuda.manual_seed_all(seed)

torch.backends.cudnn.deterministic = True

torch.backends.cudnn.benchmark = False

os.environ['PYTHONHASHSEED'] = str(seed)

# 分类

if __name__ == '__main__':

# 读数据

config = Config(

data_path="dataset_clf/data.csv",

name="MLP",

batch_size=128,

learning_rate=0.000005,

epoch=200

)

# 搭模型

clf = MLP(

input_n=len(config.input_col),

output_n=len(config.output_class),

num_layer=4,

layer_list=[10,10,10,10],

dropout=0.5

)

print(clf)

# 训练模型并评价模型

model = CLF_Model(clf, config)

model.run()

MLP_clf.py

import torch

from torch.nn import Linear, ReLU, ModuleList, Sequential, Dropout, Softmax, Tanh

import torch.nn.functional as F

class MLP(torch.nn.Module):

# 默认三层隐藏层,分别有128个 64个 16个神经元

def __init__(self, input_n, output_n, num_layer=3, layer_list=[128, 64, 16], dropout=0.5):

"""

:param input_n: int 输入神经元个数

:param output_n: int 输出神经元个数

:param num_layer: int 隐藏层层数

:param layer_list: list(int) 每层隐藏层神经元个数

:param dropout: float 训练完丢掉多少

"""

super(MLP, self).__init__()

self.input_n = input_n

self.output_n = output_n

self.num_layer = num_layer

self.layer_list = layer_list

# 输入层

self.input_layer = Sequential(

Linear(input_n, layer_list[0], bias=False),

ReLU()

)

# 隐藏层

self.hidden_layer = Sequential()

for index in range(num_layer-1):

self.hidden_layer.extend([Linear(layer_list[index], layer_list[index+1], bias=False), ReLU()])

self.dropout = Dropout(dropout)

# 输出层

self.output_layer = Sequential(

Linear(layer_list[-1], output_n, bias=False),

Softmax(dim=1),

)

def forward(self, x):

input = self.input_layer(x)

hidden = self.hidden_layer(input)

hidden = self.dropout(hidden)

output = self.output_layer(hidden)

return output

util.py

import sys

import numpy as np

import pandas as pd

import torch

import torch.nn.functional as F

from matplotlib import pyplot as plt

from sklearn import metrics

from sklearn.metrics import mean_squared_error, r2_score

from sklearn.model_selection import train_test_split

import time

from datetime import timedelta

# 一个数据格式。感觉这玩意好多余啊,但是nlp写多了就很习惯的写了一个上去 => 主要是不写没法封装

class Dataset(torch.utils.data.Dataset):

def __init__(self, data_df):

self.label = torch.from_numpy(data_df['label'].values)

self.data = torch.from_numpy(data_df[data_df.columns[:-1]].values).to(torch.float32)

# 每次迭代取出对应的data和author

def __getitem__(self, idx):

batch_data = self.get_batch_data(idx)

batch_label = self.get_batch_label(idx)

return batch_data, batch_label

# 下面的几条没啥用其实,就是为__getitem__服务的

def classes(self):

return self.label

def __len__(self):

return self.data.size(0)

def get_batch_label(self, idx):

return np.array(self.label[idx])

def get_batch_data(self, idx):

return self.data[idx]

# 存数据,加载数据用的

class Config:

def __init__(self, data_path, name, batch_size, learning_rate, epoch):

"""

:param data_path: string 数据文件路径

:param name: string 模型名字

:param batch_size: int 多少条数据组成一个batch

:param learning_rate: float 学习率

:param epoch: int 学几轮

"""

self.name = name

self.data_path = data_path

self.batch_size = batch_size

self.learning_rate = learning_rate

self.epoch = epoch

self.train_loader, self.dev_loader, self.test_loader = self.load_tdt()

self.input_col, self.output_class = self.get_class()

# 加载train, dev, test,把数据封装成Dataloader类

def load_tdt(self):

file = self.read_file()

train_dev_test = self.cut_data(file)

tdt_loader = [self.load_data(i) for i in train_dev_test]

return tdt_loader[0], tdt_loader[1], tdt_loader[2]

# 读文件

def read_file(self):

file = pd.read_csv(self.data_path, encoding="utf-8-sig", index_col=None)

# 保险起见,确认最后一列列名为label

file.columns.values[-1] = "label"

self.if_nan(file)

return file

# 切7:1:2 => 训练:验证:测试

def cut_data(self, data_df):

try:

train_df, test_dev_df = train_test_split(data_df, test_size=0.3, random_state=1129, stratify=data_df["label"])

dev_df, test_df = train_test_split(test_dev_df, test_size=0.66, random_state=1129, stratify=test_dev_df["label"])

except ValueError:

train_df, test_dev_df = train_test_split(data_df, test_size=0.3, random_state=1129)

dev_df, test_df = train_test_split(test_dev_df, test_size=0.66, random_state=1129)

return [train_df, dev_df, test_df]

# Dataloader 封装进去

def load_data(self, data_df):

dataset = Dataset(data_df)

return torch.utils.data.DataLoader(dataset, batch_size=self.batch_size)

# 检验输入输出是否有空值

def if_nan(self, data):

if data.isnull().any().any():

empty = data.isnull().any()

print(empty[empty].index)

print("Empty data exists")

sys.exit(0)

# 后面输出混淆矩阵用的

def get_class(self):

file = self.read_file()

label = file[file.columns[-1]]

label = list(set(list(label)))

return file.columns[:-1], label

# 跑clf用的,里面包含了训练,测试,评价等等的代码

class CLF_Model:

def __init__(self, model, config):

self.model = model

self.config = config

def run(self):

self.train(self.model)

def train(self, model):

dev_best_loss = float('inf')

start_time = time.time()

# 模型为训练模式

model.train()

# 定义优化器

optimizer = torch.optim.Adam(model.parameters(), lr=self.config.learning_rate)

# 记录训练、验证的准确率和损失

acc_list = [[], []]

loss_list = [[], []]

# 记录损失不下降的epoch数,到达20之后就直接退出 => 训练无效,再训练下去可能过拟合

break_epoch = 0

for epoch in range(self.config.epoch):

print('Epoch [{}/{}]'.format(epoch + 1, self.config.epoch))

for index, (trains, labels) in enumerate(self.config.train_loader):

# 归零

model.zero_grad()

# 得到预测结果,是一堆概率

outputs = model(trains)

# 交叉熵计算要long的类型

labels = labels.long()

# 计算交叉熵损失

loss = F.cross_entropy(outputs, labels)

# 反向传播loss

loss.backward()

# 优化参数

optimizer.step()

# 每100个迭代或者跑完一个epoch后,验证一下

if (index % 100 == 0 and index != 0) or index == len(self.config.train_loader) - 1:

true = labels.data.cpu()

# 预测类别

predict = torch.max(outputs.data, 1)[1].cpu()

# 计算训练准确率

train_acc = metrics.accuracy_score(true, predict)

# 计算验证准确率和loss

dev_acc, dev_loss = self.evaluate(model)

# 查看验证loss是不是进步了

if dev_loss < dev_best_loss:

dev_best_loss = dev_loss

improve = '*'

break_epoch = 0

else:

improve = ''

break_epoch += 1

time_dif = self.get_time_dif(start_time)

# 输出阶段性结果

msg = 'Iter: {0:>6}, Train Loss: {1:>5.3}, Train Acc: {2:>6.3%}, Val Loss: {3:>5.3}, Val Acc: {4:>6.3%}, Time: {5} {6}'

print(msg.format(index, loss.item(), train_acc, dev_loss, dev_acc, time_dif, improve))

# 为了画图准备的,记录每个epoch的结果

if index == len(self.config.train_loader) - 1:

acc_list[0].append(train_acc)

acc_list[1].append(dev_acc)

loss_list[0].append(loss.item())

loss_list[1].append(dev_loss)

# 验证集评估时模型编程验证模式了,现在变回训练模式

model.train()

# 20个epoch损失不变,直接退出训练

if break_epoch > 20:

self.config.epoch = epoch+1

break

# 测试

self.test(model)

# 画图

self.draw_curve(acc_list, loss_list, self.config.epoch)

def test(self, model):

start_time = time.time()

# 测试准确率,测试损失,测试分类报告,测试混淆矩阵

test_acc, test_loss, test_report, test_confusion = self.evaluate(model, test=True)

msg = 'Test Loss: {0:>5.3}, Test Acc: {1:>6.3%}'

print(msg.format(test_loss, test_acc))

print("Precision, Recall and F1-Score...")

print(test_report)

print("Confusion Matrix...")

print(test_confusion)

time_dif = self.get_time_dif(start_time)

print("Time usage:", time_dif)

def evaluate(self, model, test=False):

# 模型模式变一下

model.eval()

loss_total = 0

predict_all = np.array([], dtype=int)

labels_all = np.array([], dtype=int)

# 如果是测试模式(这一段写的不是很好)

if test:

with torch.no_grad():

for (dev, labels) in self.config.test_loader:

outputs = model(dev)

labels = labels.long()

loss = F.cross_entropy(outputs, labels)

loss_total += loss

labels = labels.data.cpu().numpy()

predict = torch.max(outputs.data, 1)[1].cpu().numpy()

labels_all = np.append(labels_all, labels)

predict_all = np.append(predict_all, predict)

acc = metrics.accuracy_score(labels_all, predict_all)

report = metrics.classification_report(labels_all, predict_all, target_names=[str(i) for i in self.config.get_class()[1]], digits=4)

confusion = metrics.confusion_matrix(labels_all, predict_all)

return acc, loss_total / len(self.config.dev_loader), report, confusion

# 不是测试模式

with torch.no_grad():

for (dev, labels) in self.config.dev_loader:

outputs = model(dev)

labels = labels.long()

loss = F.cross_entropy(outputs, labels)

loss_total += loss

labels = labels.data.cpu().numpy()

predict = torch.max(outputs.data, 1)[1].cpu().numpy()

labels_all = np.append(labels_all, labels)

predict_all = np.append(predict_all, predict)

acc = metrics.accuracy_score(labels_all, predict_all)

return acc, loss_total / len(self.config.dev_loader)

# 算时间损耗

def get_time_dif(self, start_time):

end_time = time.time()

time_dif = end_time - start_time

return timedelta(seconds=int(round(time_dif)))

# 画图

def draw_curve(self, acc_list, loss_list, epochs):

x = range(0, epochs)

y1 = loss_list[0]

y2 = loss_list[1]

y3 = acc_list[0]

y4 = acc_list[1]

plt.figure(figsize=(13, 13))

plt.subplot(2, 1, 1)

plt.plot(x, y1, color="blue", label="train_loss", linewidth=2)

plt.plot(x, y2, color="orange", label="val_loss", linewidth=2)

plt.title("Loss_curve", fontsize=20)

plt.xlabel(xlabel="Epochs", fontsize=15)

plt.ylabel(ylabel="Loss", fontsize=15)

plt.legend()

plt.subplot(2, 1, 2)

plt.plot(x, y3, color="blue", label="train_acc", linewidth=2)

plt.plot(x, y4, color="orange", label="val_acc", linewidth=2)

plt.title("Acc_curve", fontsize=20)

plt.xlabel(xlabel="Epochs", fontsize=15)

plt.ylabel(ylabel="Accuracy", fontsize=15)

plt.legend()

plt.savefig("images/"+self.config.name+"_Loss&acc.png")

1.3 结果

训练ing……

第三类的精确率感人,不过其他分类效果挺好的。感觉是数据集的问题,悄悄拿sklearn试了一下,就差1%。

曲线如下(感觉不是正常的曲线,主要是数据集的问题,70%的数据区分度很大,剩下的很难辨认)

2 回归

2.0 数据集

用的2023美赛春季赛Y题数据,在原有的数据集上加了很多船的参数,再把两个 dataset 合一起。

预处理的操作简单暴力,重复值的行删掉,部分含空值多的行删掉,方便填充的随机森林下,不方便填充的直接暴力填0。

平时肯定是不能这么干的,但是这里我们只是需要一个数据集而已,重点还是模型。

data.csv(2793x39)=> 已经包括 label 了

label.csv(2793x1)

2.1 网络架构

torch 输出的架构如下

一共是4层隐藏层(512->128->32->8)

也尝试过 10->10->10 和一些大的复杂的多层感知机,效果都一般。

2.2 代码

回归任务的相关文件如下

data.csv 回归数据集

MLP_reg.py 回归模型架构

run.py 主函数

utils.py 相关函数和类

run.py

import os

import numpy

import torch

import random

from utils import Config, CLF_Model, REG_Model

from clf_model.MLP_clf import MLP

seed = 1129

random.seed(seed)

numpy.random.seed(seed)

torch.manual_seed(seed)

torch.cuda.manual_seed(seed)

torch.cuda.manual_seed_all(seed)

torch.backends.cudnn.deterministic = True

torch.backends.cudnn.benchmark = False

os.environ['PYTHONHASHSEED'] = str(seed)

from reg_model.MLP_reg import MLP

# 回归

if __name__ == '__main__':

config = Config(

data_path="dataset_reg/data.csv",

name="MLP",

batch_size=16,

learning_rate=0.015,

epoch=200

)

# 看是几输出问题

reg = MLP(

input_n=len(config.input_col),

output_n=1,

num_layer=4,

layer_list=[512, 128, 32, 8],

dropout=0.5

)

print(reg)

model = REG_Model(reg, config)

model.run()

utils.py

import sys

import numpy as np

import pandas as pd

import torch

import torch.nn.functional as F

from matplotlib import pyplot as plt

from sklearn import metrics

from sklearn.metrics import mean_squared_error, r2_score

from sklearn.model_selection import train_test_split

import time

from datetime import timedelta

# 一个数据格式。感觉这玩意好多余啊,但是nlp写多了就很习惯的写了一个上去 => 主要是不写没法封装

class Dataset(torch.utils.data.Dataset):

def __init__(self, data_df):

self.label = torch.from_numpy(data_df['label'].values)

self.data = torch.from_numpy(data_df[data_df.columns[:-1]].values).to(torch.float32)

# 每次迭代取出对应的data和author

def __getitem__(self, idx):

batch_data = self.get_batch_data(idx)

batch_label = self.get_batch_label(idx)

return batch_data, batch_label

# 下面的几条没啥用其实,就是为__getitem__服务的

def classes(self):

return self.label

def __len__(self):

return self.data.size(0)

def get_batch_label(self, idx):

return np.array(self.label[idx])

def get_batch_data(self, idx):

return self.data[idx]

# 存数据,加载数据用的

class Config:

def __init__(self, data_path, name, batch_size, learning_rate, epoch):

"""

:param data_path: string 数据文件路径

:param name: string 模型名字

:param batch_size: int 多少条数据组成一个batch

:param learning_rate: float 学习率

:param epoch: int 学几轮

"""

self.name = name

self.data_path = data_path

self.batch_size = batch_size

self.learning_rate = learning_rate

self.epoch = epoch

self.train_loader, self.dev_loader, self.test_loader = self.load_tdt()

self.input_col, self.output_class = self.get_class()

# 加载train, dev, test,把数据封装成Dataloader类

def load_tdt(self):

file = self.read_file()

train_dev_test = self.cut_data(file)

tdt_loader = [self.load_data(i) for i in train_dev_test]

return tdt_loader[0], tdt_loader[1], tdt_loader[2]

# 读文件

def read_file(self):

file = pd.read_csv(self.data_path, encoding="utf-8-sig", index_col=None)

# 保险起见,确认最后一列列名为label

file.columns.values[-1] = "label"

self.if_nan(file)

return file

# 切7:1:2 => 训练:验证:测试

def cut_data(self, data_df):

try:

train_df, test_dev_df = train_test_split(data_df, test_size=0.3, random_state=1129, stratify=data_df["label"])

dev_df, test_df = train_test_split(test_dev_df, test_size=0.66, random_state=1129, stratify=test_dev_df["label"])

except ValueError:

train_df, test_dev_df = train_test_split(data_df, test_size=0.3, random_state=1129)

dev_df, test_df = train_test_split(test_dev_df, test_size=0.66, random_state=1129)

return [train_df, dev_df, test_df]

# Dataloader 封装进去

def load_data(self, data_df):

dataset = Dataset(data_df)

return torch.utils.data.DataLoader(dataset, batch_size=self.batch_size)

# 检验输入输出是否有空值

def if_nan(self, data):

if data.isnull().any().any():

empty = data.isnull().any()

print(empty[empty].index)

print("Empty data exists")

sys.exit(0)

# 后面输出混淆矩阵用的

def get_class(self):

file = self.read_file()

label = file[file.columns[-1]]

label = list(set(list(label)))

return file.columns[:-1], label

# 跑reg用的,里面包含了训练,测试,评价等等的代码

class REG_Model:

def __init__(self, model, config):

self.model = model

self.config = config

def run(self):

self.train(self.model)

def train(self, model):

dev_best_loss = float('inf')

start_time = time.time()

# 模型为训练模式

model.train()

# 定义优化器

optimizer = torch.optim.Adam(model.parameters(), lr=self.config.learning_rate)

acc_list = [[], []]

loss_list = [[], []]

# 记录损失不下降的epoch数,到达20之后就直接退出 => 训练无效,再训练下去可能过拟合

break_epoch = 0

for epoch in range(self.config.epoch):

print('Epoch [{}/{}]'.format(epoch + 1, self.config.epoch))

for index, (trains, labels) in enumerate(self.config.train_loader):

# 归零

model.zero_grad()

# 得到预测结果

outputs = model(trains)

# MSE计算要float的类型

labels = labels.to(torch.float)

# 计算MSE损失

loss = torch.nn.MSELoss()(outputs, labels)

# 反向传播loss

loss.backward()

# 优化参数

optimizer.step()

# 每100个迭代或者跑完一个epoch后,验证一下

if (index % 100 == 0 and index != 0) or index == len(self.config.train_loader) - 1:

true = labels.data.cpu()

# 预测数据

predict = outputs.data.cpu()

# 计算训练准确度 R2

train_acc = r2_score(true, predict)

# 计算验证准确度 R2 和 loss

dev_acc, dev_loss, dev_mse = self.evaluate(model)

# 查看验证loss是不是进步了

if dev_loss < dev_best_loss:

dev_best_loss = dev_loss

improve = '*'

break_epoch = 0

else:

improve = ''

break_epoch += 1

time_dif = self.get_time_dif(start_time)

# 输出阶段性结果

msg = 'Iter: {0:>6}, Train Loss: {1:>5.3}, Train R2: {2:>6.3}, Val Loss: {3:>5.3}, Val R2: {4:>6.3}, Val Mse: {5:>6.3}, Time: {6} {7}'

print(msg.format(index, loss.item(), train_acc, dev_loss, dev_acc, dev_mse, time_dif, improve))

# 为了画图准备的,记录每个epoch的结果

if index == len(self.config.train_loader) - 1:

acc_list[0].append(train_acc)

acc_list[1].append(dev_acc)

loss_list[0].append(loss.item())

loss_list[1].append(dev_loss)

# 验证集评估时模型编程验证模式了,现在变回训练模式

model.train()

# 20个epoch损失不变,直接退出训练

if break_epoch > 20:

self.config.epoch = epoch+1

break

# 测试

self.test(model)

# 画图

self.draw_curve(acc_list, loss_list, self.config.epoch)

def test(self, model):

start_time = time.time()

# 测试准确度 R2,测试损失,测试MSE

test_acc, test_loss, mse = self.evaluate(model, test=True)

msg = 'Test R2: {0:>5.3}, Test loss: {1:>6.3}, Test MSE: {2:>6.3}'

print(msg.format(test_acc, test_loss, mse))

time_dif = self.get_time_dif(start_time)

print("Time usage:", time_dif)

def evaluate(self, model, test=False):

# 模型模式变一下

model.eval()

loss_total = 0

predict_all = np.array([], dtype=int)

labels_all = np.array([], dtype=int)

# 如果是测试模式(这一段写的不是很好)

if test:

with torch.no_grad():

for (dev, labels) in self.config.test_loader:

outputs = model(dev)

labels = labels.to(torch.float)

loss = torch.nn.MSELoss()(outputs, labels)

loss_total += loss

labels = labels.data.cpu().numpy()

predict = outputs.data.cpu().numpy()

labels_all = np.append(labels_all, labels)

predict_all = np.append(predict_all, predict)

# 不是测试模式

else:

with torch.no_grad():

for (dev, labels) in self.config.dev_loader:

outputs = model(dev)

labels = labels.long()

loss = torch.nn.MSELoss()(outputs, labels)

loss_total += loss

labels = labels.data.cpu().numpy()

predict = outputs.data.cpu().numpy()

labels_all = np.append(labels_all, labels)

predict_all = np.append(predict_all, predict)

r2 = r2_score(labels_all, predict_all)

mse = mean_squared_error(labels_all, predict_all)

if test:

return r2, loss_total / len(self.config.test_loader), mse

else:

return r2, loss_total / len(self.config.dev_loader), mse

# 算时间损耗

def get_time_dif(self, start_time):

end_time = time.time()

time_dif = end_time - start_time

return timedelta(seconds=int(round(time_dif)))

# 画图

def draw_curve(self, acc_list, loss_list, epochs):

x = range(0, epochs)

y1 = loss_list[0]

y2 = loss_list[1]

y3 = acc_list[0]

y4 = acc_list[1]

plt.figure(figsize=(13, 13))

plt.subplot(2, 1, 1)

plt.plot(x, y1, color="blue", label="train_loss", linewidth=2)

plt.plot(x, y2, color="orange", label="val_loss", linewidth=2)

plt.title("Loss_curve", fontsize=20)

plt.xlabel(xlabel="Epochs", fontsize=15)

plt.ylabel(ylabel="Loss", fontsize=15)

plt.legend()

plt.subplot(2, 1, 2)

plt.plot(x, y3, color="blue", label="train_acc", linewidth=2)

plt.plot(x, y4, color="orange", label="val_acc", linewidth=2)

plt.title("Acc_curve", fontsize=20)

plt.xlabel(xlabel="Epochs", fontsize=15)

plt.ylabel(ylabel="Accuracy", fontsize=15)

plt.legend()

plt.savefig("images/"+self.config.name+"_Loss&acc.png")

MLP_reg.py

import torch

from torch.nn import Linear, ReLU, ModuleList, Sequential, Dropout, Softmax, Tanh

import torch.nn.functional as F

class MLP(torch.nn.Module):

def __init__(self, input_n, output_n, num_layer=2, layer_list=[16, 8], dropout=0.5):

super(MLP, self).__init__()

self.input_n = input_n

self.output_n = output_n

self.num_layer = num_layer

self.layer_list = layer_list

self.input_layer = Sequential(

Linear(input_n, layer_list[0], bias=False),

ReLU()

)

self.hidden_layer = Sequential()

for index in range(num_layer-1):

self.hidden_layer.extend([Linear(layer_list[index], layer_list[index+1], bias=False), ReLU()])

self.dropout = Dropout(dropout)

self.output_layer = Sequential(

Linear(layer_list[-1], output_n, bias=False),

# ReLU()

# Softmax(dim=1),

)

def forward(self, x):

input = self.input_layer(x)

hidden = self.hidden_layer(input)

hidden = self.dropout(hidden)

output = self.output_layer(hidden)

output = output.view(-1)

return output

2.3 结果

训练ing……

R2 有0.73。怎么说呢,还可以吧,不高不低。 拿 sklearn 默认的 MLP 才-2.7400039908485083,SVR才-0.15191155233964238。

曲线如下(感觉不是正常的曲线,训练集太飘了=> 也可能是epoch不到位)

3 代码(可直接食用)

记得一键三连噢~~

参考阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: