多层感知机MLP实现分类常见问题,及二分类示例

就跟着代码的顺序说问题

先留一些我的数据,可以参考一下数据类型:

all_data.rar - 蓝奏云

第一章 文件读取

%matplotlib inline
import numpy as np
import pandas as pd
import torch
from torch import nn
from d2l import torch as d2l

train_data = pd.read_csv("all_data.csv")
train_data.shape

#(198, 401)

        因为我这个例子数据不多,就198条,所以就不专门设立验证集了,用K折交叉验证的方法来验证。

        数据最后一列为标签,所以数据的特征列为400,共198条数据,先把训练数据和标签分开。

train_features = train_data.iloc[:,0:-1].values   #0:-1  就是取data中的第0列开始倒数第一列结 
                                                  #束,包括0列不包括倒数第一列
train_labels = train_data.iloc[:,400:]   

print(train_features.shape)
print(train_labels.shape)
type(train_features)

#(198, 400)
#(198, 1)
#numpy.ndarray

        可以看到训练数据和标签已经分开了,可以查看变量表看看分的是否是正确的,而且现在的数据格式为np.ndarray,到这里文件的读取就已经结束了。

第二章 数据预处理

        首先需要对数据进行归一化操作,这个归一化的方法有好几种,看自己需求吧,我的这个归一化的方法是:对于每一个特征值x,(x-该列最小值)/(该列最大值-该列最小值)

def maxminnorm(array):
    maxcols=array.max(axis=0)
    mincols=array.min(axis=0)
    data_shape = array.shape
    data_rows = data_shape[0]
    data_cols = data_shape[1]
    t=np.empty((data_rows,data_cols))
    for i in range(data_cols):
        t[:,i]=(array[:,i]-mincols[i])/(maxcols[i]-mincols[i])
    return t

train_features = maxminnorm(train_features)
type(train_features)

#numpy.ndarray

处理了之后,数据中可能会出现一些无值的情况,也就是特征值为nan,这种情况出现的原因是该列特征值的数值都相同,最大值和最小值相同,相减为0,所以成为了nan。

        特征值为nan的需要进行进一步进行填0或者直接删除的操作,nan是没有数值的,如果不处理计算会报错。我是进行填0操作。

train_features = np.nan_to_num(train_features)
#这个将nan填0的函数只适用于numpy格式的数据,如果是其
#他格式的数据,可以自行查询对应格式的填0函数

        接下来就要处理数据的标签了,因为是分类任务,所以标签要变成one-hot的编码格式,如果数据标签不是,就需要进行转变

train_labels = torch.tensor(train_labels.values)
#将标签的数据类型从ndarray转成tensor
train_labels = torch.nn.functional.one_hot(train_labels,num_classes=2)
#这个one-hot编码的函数适用于tensor数据类型,所以先把数据转成了tensor类型,
#其他类型的数据可以考虑转成tensor,或者查一查又没有该类型数据的one-hot转换函数
train_labels.shape

#torch.Size([198, 1, 2])

        上面的这个num-classes表示的是要表示成几位的编码,2就是【0,1】、【1,0】这样两位的编码,one-hot的函数还有一个要求就是,你标签的数值必须要小于num_classes的值,比如我这个的标签就只能是0或者1,不能有大于2的值。

        现在数据的维度变成了198*1*2,正确的应该是198*2,多了一个一维,输出该变量部分。

print(train_labels[:5])

#tensor([[[1, 0]],[[1, 0]],[[1, 0]],[[1, 0]],[[1, 0]]])

        单纯只是多了一个框,直接去掉就ok,用squeeze降维函数。

train_labels = torch.squeeze(train_labels, dim=1) 

print(train_labels[:5])
#tensor([[1, 0],
        [1, 0],
        [1, 0],
        [1, 0],
        [1, 0]])

        最后一步就是数据格式的转换了,要用torch的框架,所以就都换成torch的格式,并且要是float32的格式,这是损失函数的格式要求。

train_features = torch.tensor(train_features,dtype=torch.float32)
train_labels =  torch.tensor(train_labels,dtype=torch.float32)

第三章 模型构建

        首先定义loss以及网络结构,因为是二分类,标签编码是两位,所以输出为2,并且是二分类问题loss采用BCELoss,多分类的话可以用CrossEntropyLoss,最后一层要放一个sigmoid函数,将输出限制在0-1。

loss = nn.BCELoss()

def get_net():   
    net = nn.Sequential(nn.Linear(400,256),
                        nn.ReLU(),
                        nn.Linear(256,2),
                        nn.Sigmoid()
                        )
    return net

        然后定义训练器

def train(net, train_features, train_labels, test_features, test_labels,num_epochs, learning_rate, weight_decay, batch_size):
    #     网络,训练集,        训练标签,     测试集,        测试标签,   训练次数,   学习率,       权重衰退 ,      批量数目
    train_ls, test_ls = [], []
    train_iter = d2l.load_array((train_features, train_labels), batch_size)   #取小批量样本
    # 这里使用的是Adam优化算法
    optimizer = torch.optim.Adam(net.parameters(),
                                 lr = learning_rate,
                                 weight_decay = weight_decay)
    for epoch in range(num_epochs):
        for X, y in train_iter:
            
            optimizer.zero_grad()
            l = loss(net(X), y)
            l.backward()
            optimizer.step()
        train_ls.append(loss(net(train_features), train_labels))    #log_rmse返回的是取log后差值的平方,这里用这个作为误差指标
        if test_labels is not None:
            test_ls.append(loss(net(test_features), test_labels))
    return train_ls, test_ls

        采用K折交叉验证的方法,需要先对数据进行拆分,下面是数据的拆分函数

def get_k_fold_data(k, i, X, y):
    assert k > 1
    fold_size = X.shape[0] // k
    X_train, y_train = None, None
    for j in range(k):
        idx = slice(j * fold_size, (j + 1) * fold_size)
        X_part, y_part = X[idx, :], y[idx]
        if j == i:
            X_valid, y_valid = X_part, y_part
        elif X_train is None:
            X_train, y_train = X_part, y_part
        else:
            X_train = torch.cat([X_train, X_part], 0)
            y_train = torch.cat([y_train, y_part], 0)
    return X_train, y_train, X_valid, y_valid

        下面是最终的采用K折交叉验证的训练函数

def k_fold(k, X_train, y_train, num_epochs, learning_rate, weight_decay,
           batch_size):
    train_l_sum, valid_l_sum = 0, 0
    for i in range(k):
        data = get_k_fold_data(k, i, X_train, y_train)
        net = get_net()
        train_ls, valid_ls = train(net, *data, num_epochs, learning_rate,
                                   weight_decay, batch_size)
        train_l_sum += train_ls[-1]
        valid_l_sum += valid_ls[-1]
        if i == 0:
            d2l.plot(list(range(1, num_epochs + 1)), [train_ls, valid_ls],
                     xlabel='epoch', ylabel='rmse', xlim=[1, num_epochs],
                     legend=['train', 'valid'], yscale='log')
        print(f'折{i + 1},训练log rmse{float(train_ls[-1]):f}, '
              f'验证log rmse{float(valid_ls[-1]):f}')
    return train_l_sum / k, valid_l_sum / k

        最后进行训练与输出

k, num_epochs, lr, weight_decay, batch_size = 5, 50, 0.001, 0, 10
train_l, valid_l = k_fold(k, train_features, train_labels, num_epochs, lr,
                          weight_decay, batch_size)
print(f'{k}-折验证: 平均训练log rmse: {float(train_l):f}, '
      f'平均验证log rmse: {float(valid_l):f}')

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个简单的多层感知机实现二分类的代码示例,使用 PyTorch 框架: ```python import torch import torch.nn as nn import torch.optim as optim # 定义多层感知机模型 class MLP(nn.Module): def __init__(self, input_size, hidden_size, output_size): super(MLP, self).__init__() self.fc1 = nn.Linear(input_size, hidden_size) self.relu = nn.ReLU() self.fc2 = nn.Linear(hidden_size, output_size) self.sigmoid = nn.Sigmoid() def forward(self, x): x = self.fc1(x) x = self.relu(x) x = self.fc2(x) x = self.sigmoid(x) return x # 准备训练数据 x_train = torch.tensor([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]]) y_train = torch.tensor([[0.0], [1.0], [1.0], [0.0]]) # 定义模型参数 input_size = 2 hidden_size = 4 output_size = 1 lr = 0.1 epochs = 1000 # 初始化模型和优化器 model = MLP(input_size, hidden_size, output_size) optimizer = optim.SGD(model.parameters(), lr=lr) # 训练模型 for epoch in range(epochs): # 前向传播 y_pred = model(x_train) # 计算损失 loss_fn = nn.MSELoss() loss = loss_fn(y_pred, y_train) # 反向传播 optimizer.zero_grad() loss.backward() optimizer.step() # 每 100 步输出一次损失 if epoch % 100 == 0: print("Epoch {}, Loss {}".format(epoch, loss.item())) # 测试模型 x_test = torch.tensor([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]]) y_test = model(x_test) print(y_test) ``` 上述代码实现了一个包含一个隐藏层的多层感知机模型,使用均方误差作为损失函数,使用随机梯度下降算法进行优化。训练完毕后,对模型进行测试并输出预测结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值