鱼C论坛

 找回密码
 立即注册
查看: 42|回复: 1

简单神经网络使用k折交叉验证报错

[复制链接]
发表于 昨天 20:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
训练模型代码
#使用dnn模型
import torch 
import torch.nn as nn
from torch.utils import data
from torch.utils.data import Dataset,DataLoader
from torch import optim

#定义神经网络模型
dropout1, dropout2 = 0.3, 0.6
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()  # 继承需要用 SimpleNN
        self.dense = nn.Sequential(
            nn.Flatten(),
            nn.Linear(12, 128),
            nn.ReLU(),  
            nn.Dropout(dropout1),
            nn.Linear(128, 256),
            nn.ReLU(),  
            nn.Dropout(dropout2),
            nn.Linear(256, 1),
        )
       
    def forward(self, X):
        x = self.dense(X)
        output = torch.sigmoid(x)
        return output

    
#初始化模型和优化器
nn_model = SimpleNN()
loss = nn.BCELoss() #定义损失函数
optimizer = optim.Adam(nn_model.parameters(),lr=0.0001) #定义优化器

#初始化列表
acc_list = []
loss_list = []

#k折交叉验证选取训练集与验证集
def get_k_fold_data(k, i, X, y):
    assert k > 1
    fold_size = len(X) // k
    X_train, y_train = None, None
    for j in range(k):
        start = j * fold_size
        end = (j + 1) * fold_size
        if j == i:
            X_valid, y_valid = X.iloc[start:end], y.iloc[start:end]
        elif X_train is None:
            X_train, y_train = X.iloc[:start], y.iloc[start:end]
        else:
            X_train = pd.concat([X_train, X.iloc[start:end]], ignore_index=True)
            y_train = pd.concat([y_train, y.iloc[start:end]], ignore_index=True)
    return X_train, y_train, X_valid, y_valid


# 开始训练
k = 5
batch_size = 99
num_epochs = 1000


for i in range(k):
    X_train, y_train, X_valid, y_valid = get_k_fold_data(k, i, X, y)
    print(f'FOLD {i}')
    print('--------------------------------')
    
    #将DataFrame数据转换为NumPy数组,然后再转换为PyTorch张量
    X_train = torch.tensor(X_train.astype(np.float32).values, dtype=torch.float32)
    y_train = torch.tensor(y_train.astype(np.float32).values, dtype=torch.float32)
    X_valid = torch.tensor(X_valid.astype(np.float32).values, dtype=torch.float32)
    y_valid = torch.tensor(y_valid.astype(np.float32).values, dtype=torch.float32)
    
    #创建数据集
    train_dataset = data.TensorDataset(X_train, y_train)
    valid_dataset = data.TensorDataset(X_valid, y_valid)

    # 获取一个数据迭代器
    train_iter = DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True,num_workers=2)#shuffle=True相当于sampler=RandomSampler(dataset)
    valid_iter = DataLoader(dataset=valid_dataset,batch_size=batch_size,shuffle=True,num_workers=2)
    
    #开始迭代
    for epoch in range(num_epochs):
        train_loss = 0
        num_right = 0
        for tensor_x, tensor_y in train_iter:#训练集执行梯度更新
            tensor_x = tensor_x.float()
            tensor_y = tensor_y.float().reshape(-1, 1)
            optimizer.zero_grad() #梯度清零
            pre_train = nn_model(tensor_x)
            train_l = loss(pre_train, tensor_y) #损失应避免与全局变量loss重名
            train_l.backward()#前向传播
            optimizer.step()#梯度下降

            train_loss += train_l.item() * len(tensor_x)
            result = [1 if out >= 0.5 else 0 for out in pre_train]
            num_right += np.sum(np.array(result) == tensor_y.numpy().reshape(-1))

            train_loss = train_loss / len(train_iter.dataset)
            train_accuracy = num_right / len(train_iter.dataset)

        if epoch % 200 == 0:
            print('Loss: {} Accuracy: {} Epoch:{}'.format(train_loss, train_accuracy, epoch))
        
        with torch.no_grad():
            valid_loss = 0
            num_right = 0
            for tensor_x, tensor_y in valid_iter:
                tensor_x = tensor_x.float()
                tensor_y = tensor_y.float().reshape(-1, 1)
                pre_valid = nn_model(tensor_x)
                valid_l = loss(pre_valid, tensor_y)
                valid_loss += valid_l.item() * len(tensor_x)
                result = [1 if out >= 0.5 else 0 for out in pre_valid]
                num_right += np.sum(np.array(result) == tensor_y.numpy().reshape(-1))
            
            valid_loss = valid_loss / len(valid_iter.dataset)
            valid_accuracy = num_right / len(valid_iter.dataset)
        
            if epoch % 200 == 0:
                print('Valid Loss: {} Accuracy: {} Epoch:{}'.format(valid_loss, valid_accuracy, epoch))
        
    #将每次迭代的结果写入列表
    loss_list.append(valid_loss)
    acc_list.append(valid_accuracy)
        
print('Training Ended')
print('Average Loss: {} Average Accuracy: {}'.format(np.mean(loss_list), np.mean(acc_list)))

报错代码
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[28], line 75
     72 y_valid = torch.tensor(y_valid.astype(np.float32).values, dtype=torch.float32)
     74 #创建数据集
---> 75 train_dataset = data.TensorDataset(X_train, y_train)
     76 valid_dataset = data.TensorDataset(X_valid, y_valid)
     78 # 获取一个数据迭代器

File /opt/conda/lib/python3.10/site-packages/torch/utils/data/dataset.py:204, in TensorDataset.__init__(self, *tensors)
    203 def __init__(self, *tensors: Tensor) -> None:
--> 204     assert all(tensors[0].size(0) == tensor.size(0) for tensor in tensors), "Size mismatch between tensors"
    205     self.tensors = tensors

AssertionError: Size mismatch between tensors
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 昨天 20:22 | 显示全部楼层
这个错误的原因是`X_train`和`y_train`的大小不匹配。要解决这个问题,可以检查`get_k_fold_data`函数中的索引和拼接部分,确保每个折的训练和验证集的大小正确。以下是一些您可以检查和修正的点:

1. **数据分割**:
if j == i:
       X_valid, y_valid = X.iloc[start:end], y.iloc[start:end]
   else:
       X_train = pd.concat([X_train, X.iloc[start:end]], ignore_index=True) if X_train is not None else X.iloc[start:end]
       y_train = pd.concat([y_train, y.iloc[start:end]], ignore_index=True) if y_train is not None else y.iloc[start:end]

2. **数据类型**:
   确保`X`和`y`是Pandas DataFrame和Series对象,因此可以使用`.iloc`进行正确的索引。

3. **确保交叉验证正确**:
   验证确保每次k-fold划分后的`X_train`和`y_train`长度一致。

4. **调试信息**:
   可以在每次生成`TensorDataset`之前打印`X_train.shape`和`y_train.shape`,检查它们是否一致。

通过这些检查和修正,应该能够解决您的问题。如果仍有错误,请根据具体信息分析`X`和`y`的内容和形状。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-23 02:45

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表