神经网络拟合离散标签值

1. 数据预处理

1.1 添加参数解析

为了方便管理模型和训练等参数,统一用参数解析。

def parse_args():
    """
    解析命令行参数并返回参数对象。

    返回:
    - args (argparse.Namespace): 解析后的参数对象
    """
    parser = argparse.ArgumentParser(description='命令行参数解析示例')

    # 添加参数
    #代表输入文件的名称:g0-25%.xlsx、l0.4-2.6.xlsx、s0.4-1.6.xlsx、y0.8-4.0.xlsx
    parser.add_argument('--input', type=str, default='g0-25%.xlsx', help='数据文件路径')
    #代表预测excel中哪一列的参数值,比如要预测g0-25%.xlsx中g取0的这一列
    parser.add_argument('--predict_para', type=float, default=12.5, help='代表预测excel中哪一列的参数值')
    parser.add_argument('--batch_size', type=int, default=4, help='每批次的样本数量,默认值是 4')
    parser.add_argument('--epochs', type=int, default=100, help='训练的轮数,默认值是100')
    parser.add_argument('--learning_rate', type=float, default=0.001, help='学习率,默认值是 0.001')

    # 解析参数
    args = parser.parse_args()

    return args

1.2 数据预处理逻辑

最近一个小项目需要搭建神经网络根据输入数据的特征去拟合对应的标签值
输入是excel的.xlsx文件,一共是1400x12的12列数据,第一列是时间,第2-第12列都是对应的数据,第一行是对应的标签值;使用pandas库读取。
在这里插入图片描述

args = parse_args()

file_path = args.input  # 请替换为实际的数据文件路径

# 读取 Excel 文件
df = pd.read_excel(file_path)
data = df.to_numpy()[:, 1:]

# 标签就是第一行对应的离散标签值
labels = np.array(df.columns)[1:].astype(np.float32)
labels = np.round(labels, 2)

1.3 标签处理逻辑

从第一行的标签值来看,每个标签真实值都是离散值,我们可以将其映射为0、1、2…,把回归问题当成分类问题来,更有利于模型的拟合。

scaler = StandardScaler()
train_features = train_df.iloc[:, :-output_df.shape[1]]
train_labels = train_df.iloc[:, -output_df.shape[1]:]

test_features = test_df.iloc[:, :-output_df.shape[1]]
test_labels = test_df.iloc[:, -output_df.shape[1]:]

X_train = scaler.fit_transform(train_features)
y_train = np.array(train_labels)
X_val = scaler.transform(test_features)
y_val = np.array(test_labels)

1.4 构建特征和标签

这里,data是1400x11维度的数据,将其转置``,则表示成11组(1400, 1)的数据,刚好对应11个离散标签值。标签y则是(11, 1),对应11个映射好的标签值

# 构建特征和标签
X: object = data.T  # [样本数, 特征数]
y = label_indices  # 标签

1.5 数据归一化、转torch

# 数据预处理:标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 创建 Dataset 对象
dataset = CustomDataset(X_scaled, label_indices)

# 创建 DataLoader 对象
batch_size = args.batch_size
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
#实例化网络模型,output对应预测的标签值的数量
model = CNNClassifier(fc1_channels=44544, output=11)

1.6 实现Dataset类

这里,对data添加维度,为(11, 1, 1400),labels 转int型,最后都转tensor
经过上述的转置后,这里的__len__,就是return的11,正好是11组数据,__getitem__正好根据索引idx返回对应的每一组数据。

# 自定义 Dataset 类
class CustomDataset(Dataset):
    def __init__(self, data, labels):
        self.data = torch.tensor(data, dtype=torch.float32).unsqueeze(1)  # Add channel dimension
        self.labels = torch.tensor(labels, dtype=torch.int64)  # Long for classification

    def __len__(self):
        return self.data.size(0)  # Number of samples

    def __getitem__(self, idx):
        # return self.data[:, idx, :], self.labels[idx]
        return self.data[idx], self.labels[idx]

2. 定义model

这里我定义了1个CNN结合FC的网络结构。

# 定义 CNN 模型
class CNNClassifier(nn.Module):
    def __init__(self, fc1_channels, output):
        super(CNNClassifier, self).__init__()
        self.conv1 = nn.Conv1d(in_channels=1, out_channels=16, kernel_size=5)
        self.conv2 = nn.Conv1d(in_channels=16, out_channels=32, kernel_size=5)
        self.fc1 = nn.Linear(fc1_channels, 128)  # Flattened feature size is 32 * 1390
        self.fc2 = nn.Linear(128, output)  #  classes

    def forward(self, x):
        x = self.conv1(x)
        x = nn.ReLU()(x)
        x = self.conv2(x)
        x = nn.ReLU()(x)
        x = x.view(x.size(0), -1)  # Flatten
        x = self.fc1(x)
        x = nn.ReLU()(x)
        x = self.fc2(x)
        return x

3. 定义train脚本

3.1 loss和optimizer

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=args.learning_rate)

3.2 train

# 训练模型
num_epochs = args.epochs
for epoch in range(num_epochs):
    model.train()
    running_loss = 0.0
    for batch_data, batch_labels in dataloader:
        outputs = model(batch_data)
        loss = criterion(outputs, batch_labels)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        running_loss += loss.item() * batch_data.size(0)
    epoch_loss = running_loss / len(dataset)
    print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {epoch_loss:.4f}')

3.3 predict

最后在预测的时候别忘了根据上述映射关系,将预测的标签值映射回去

# 进行预测
model.eval()
with torch.no_grad():
    # 选择一个样本进行预测
    # sample_idx = 10
    sample_labels_list = [round(label, 2) for label in labels.tolist()]
    sample_idx = sample_labels_list.index(args.predict_para)
    eval_data = torch.tensor(X_scaled[sample_idx], dtype=torch.float32).unsqueeze(0).unsqueeze(0)
    predictions = model(eval_data)
    _, predicted_label_idx = torch.max(predictions, 1)
    predicted_label = labels[predicted_label_idx.item()]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Andrew_Xzw

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值