鱼C论坛

 找回密码
 立即注册
查看: 212|回复: 23

好心人帮忙看一下简单神经网络dnn模型的代码有什么问题

[复制链接]
发表于 2024-10-20 16:33:37 | 显示全部楼层 |阅读模式

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

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

x
#使用dnn模型
import torch 
import torch.nn as nn
from torch.utils import data
from torch.utils.data import DataLoader
from torch import optim

#定义神经网络模型
dropout1, dropout2 = 0.2, 0.5
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()  # 这里需要用 SimpleNN
        self.dense = nn.Sequential(
            nn.Flatten(),
            nn.Linear(5, 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


#定义损失函数
loss = nn.BCELoss()

#定义优化器
optimizer = optim.Adam(nn_model.parameters(),lr=0.001)

#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):#slice不能直接用于Series和Dataframe,pandas中需要用.iloc或 .loc作为索引下标
        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:end], 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 #该四个数据类型为dataframe

# 开始训练
acc_list = []
loss_list = []
batch_size = 99
k = 5
num_epochs = 10000
nn_model = SimpleNN()

for i in range(k):
    X_train,y_train, X_valid,y_valid = get_k_fold_data(k, i, X, y)  #获取第k折的训练集和验证集
    print(f'FOLD {i}')
    print('--------------------------------')
    # 将数据转换为NumPy数组,然后再转换为PyTorch张量
    X_train = torch.tensor(X_train.values, dtype=torch.float32)
    y_train = torch.tensor(y_train.values, dtype=torch.float32)
    X_valid = torch.tensor(X_valid.values, dtype=torch.float32)
    y_valid = torch.tensor(y_valid.values, dtype=torch.float32)

    # 获取一个数据迭代器
    train_dataset = data.TensorDataset(X_train, y_train)
    valid_dataset = data.TensorDataset(X_valid, y_valid)
    train_iter = data.DataLoader(train_dataset, batch_size, shuffle=True)
    valid_iter = data.DataLoader(valid_dataset, batch_size, shuffle=True)
    
    #开始迭代
    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)
            loss = loss(pre_train, tensor_y)
            loss.backward()#前向传播
            optimizer.step()#梯度下降

            train_loss += loss.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)
            train_accuracy = num_right / len(train_iter)

            if epoch % 100 == 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)
                loss = loss(pre_valid, tensor_y)
                valid_loss += loss.item() * len(tensor_x)
                result = [1 if out >= 0.5 else 0 for out in output]
                num_right += np.sum(np.array(result) == tensor_y.numpy().reshape(-1))
            
            valid_loss = valid_loss / len(valid_iter)
            valid_accuracy = num_right / len(valid_iter)
        
            if epoch % 100 == 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)))
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-10-20 16:42:37 | 显示全部楼层
你的代码中有几个小问题需要修复:

1. **变量初始化**:
   - `acc_list` 和 `loss_list` 未初始化,需要在代码开始时加上 `acc_list = []` 和 `loss_list = []`。

2. **对象初始化顺序**:
   - `nn_model = SimpleNN()` 应在定义优化器 `optimizer` 之前进行初始化。

3. **错误使用`shape`运算**:
   - 代码 `fold_size = X.shape // k` 不是有效的运算。需要改为 `fold_size = len(X) // k`,这样会计算每折的大小。

4. **`iloc/loc` 用法错误**:
   - 在 `get_k_fold_data` 函数中,使用 `.iloc` 时,需要指定具体的行范围。
   - 修改为 `X.iloc[start:end]` 和 `y.iloc[start:end]`。

5. **变量未定义**:
   - `pd` 需要在代码中导入,需要在代码顶部加上 `import pandas as pd`。
   - `result` 未定义,你可能需要在每次预测后将 `result` 定义为:`result = (pre_train > 0.5).numpy()`

6. **`loss` 覆盖**:
   - 在循环中定义损失时重新赋值,造成覆盖之前定义的变量,可以重命名局部变量,避免与全局变量重名,比如 `train_loss_value`。

7. **计算平均训练损失和准确率位置指引不当**:
   - 平均损失和准确率计算应该放在每个 epoch 的数据迭代结束后而不是内部。

整体修改以简化口述说明:
# 使用dnn模型
import torch 
import torch.nn as nn
from torch.utils import data
from torch.utils.data import DataLoader
from torch import optim
import numpy as np
import pandas as pd

# 定义神经网络模型
dropout1, dropout2 = 0.2, 0.5
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.dense = nn.Sequential(
            nn.Flatten(),
            nn.Linear(5, 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

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

# 初始化模型和优化器
nn_model = SimpleNN()
loss_fn = nn.BCELoss()
optimizer = optim.Adam(nn_model.parameters(), lr=0.001)

# 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, end = j * fold_size, (j + 1) * fold_size
        if j == i:
            X_valid, y_valid = X.iloc[start:end], y.iloc[start:end]
        else:
            if X_train is None:
                X_train, y_train = X.iloc[start:end], 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 

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

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('--------------------------------')
    
    X_train = torch.tensor(X_train.values, dtype=torch.float32)
    y_train = torch.tensor(y_train.values, dtype=torch.float32)
    X_valid = torch.tensor(X_valid.values, dtype=torch.float32)
    y_valid = torch.tensor(y_valid.values, dtype=torch.float32)

    train_dataset = data.TensorDataset(X_train, y_train)
    valid_dataset = data.TensorDataset(X_valid, y_valid)
    train_iter = DataLoader(train_dataset, batch_size, shuffle=True)
    valid_iter = DataLoader(valid_dataset, batch_size, shuffle=True)
    
    for epoch in range(num_epochs):
        train_loss, num_right = 0, 0
        for tensor_x, tensor_y in train_iter:
            tensor_x, tensor_y = tensor_x.float(), tensor_y.float().reshape(-1, 1)
            optimizer.zero_grad()
            pre_train = nn_model(tensor_x)
            l = loss_fn(pre_train, tensor_y)
            l.backward()
            optimizer.step()

            train_loss += l.item() * len(tensor_x)
            result = (pre_train > 0.5).numpy()
            num_right += np.sum(result == tensor_y.numpy().reshape(-1))

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

        if epoch % 100 == 0:
            print(f'Loss: {train_loss:.6f} Accuracy: {train_accuracy:.4f} Epoch: {epoch}')
        
        with torch.no_grad():
            valid_loss, num_right = 0, 0
            for tensor_x, tensor_y in valid_iter:
                tensor_x, tensor_y = tensor_x.float(), tensor_y.float().reshape(-1, 1)
                pre_valid = nn_model(tensor_x)
                l = loss_fn(pre_valid, tensor_y)
                valid_loss += l.item() * len(tensor_x)
                result = (pre_valid > 0.5).numpy()
                num_right += np.sum(result == tensor_y.numpy().reshape(-1))
            
            valid_loss /= len(valid_iter.dataset)
            valid_accuracy = num_right / len(valid_iter.dataset)

            if epoch % 100 == 0:
                print(f'Valid Loss: {valid_loss:.6f} Accuracy: {valid_accuracy:.4f} Epoch: {epoch}')
        
        loss_list.append(valid_loss)
        acc_list.append(valid_accuracy)

print('Training Ended')
print(f'Average Loss: {np.mean(loss_list):.6f} Average Accuracy: {np.mean(acc_list):.4f}')

确保更正问题后,如果有更多上下文,例如数据集的形式,可能需要进一步调整代码。

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

使用道具 举报

发表于 2024-10-20 16:44:33 | 显示全部楼层
nn_model.parameters() 应该替换为 nn_model.parameters()
X 和 y 应该是Pandas的DataFrame或Series,但在代码中没有定义。
在计算训练和验证准确率时,应该使用 pre_train 和 pre_valid 而不是 output,因为 output 在这个上下文中没有被定义。
train_accuracy 和 valid_accuracy 的计算应该在每个epoch结束后进行,而不是在每个batch结束后。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-20 17:30:12 | 显示全部楼层
FishC 发表于 2024-10-20 16:42
你的代码中有几个小问题需要修复:

1. **变量初始化**:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[188], line 68
     66 print('--------------------------------')
     67 # 将数据转换为NumPy数组,然后再转换为PyTorch张量
---> 68 X_train = torch.tensor(X_train.values, dtype=torch.float32)
     69 y_train = torch.tensor(y_train.values, dtype=torch.float32)
     70 X_valid = torch.tensor(X_valid.values, dtype=torch.float32)

TypeError: can't convert np.ndarray of type numpy.object_. The only supported types are: float64, float32, float16, complex64, complex128, int64, int32, int16, int8, uint8, and bool.

报错如上
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-20 17:30:23 | 显示全部楼层
Terence888 发表于 2024-10-20 17:30
-------------------------------------------------- ...


该错误通常是由于数据集中存在不支持的数据类型,如字符串或混合类型。处理这个问题的方法包括确保在将数据转换为Tensor之前,数据框中没有不必要的字符串数据。以下是一些排查和解决方法:

1. **检查和清理数据**:
   
   - 请确保你的 DataFrame(`X_train` 和 `X_valid`)只包含数值数据。你可以使用 `pandas` 方法来检查数据类型:
   
print(X_train.dtypes)

   - 如果发现有非数值类型的列,你可以选择删除这些列或者将其转换为数值。例如,使用 `pandas` 将类别数据转为数值类型的方法:

   
# 示例,假设 `category_column` 是类别列
     X_train['category_column'] = X_train['category_column'].astype('category').cat.codes

2. **检查是否有缺失值**:

   - 缺失值可能导致数据类型不匹配。你可以通过以下方式填补或删除缺失值:
   
X_train.fillna(0, inplace=True)  # 用0填补缺失值
     # 或者
     X_train.dropna(inplace=True)  # 删除含缺失值的行

3. **强制转换数据类型**:

   - 在确保数据全部是数值类型后,再转为`np.float32`类型:
   
X_train = X_train.astype(np.float32)
     X_valid = X_valid.astype(np.float32)

4. **确认使用了正确的DataFrame对象**:

   - 确保你在数据处理流程中没有使用错误或者已经被修改的对象。

如经过上述处理后问题仍未解决,请提供更详细的上下文或数据,以便进一步协助。

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

使用道具 举报

 楼主| 发表于 2024-10-20 18:13:31 | 显示全部楼层
FishC 发表于 2024-10-20 17:30
该错误通常是由于数据集中存在不支持的数据类型,如字符串或混合类型。处理这个问题的方法包括确保在将 ...
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Cell In[204], line 85
     83 tensor_y = tensor_y.float().reshape(-1, 1)
     84 optimizer.zero_grad() #梯度清零
---> 85 pre_train = nn_model(tensor_x)
     86 train_l = loss(pre_train, tensor_y) #损失应避免与全局变量loss重名
     87 l.backward()#前向传播

File /opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py:1518, in Module._wrapped_call_impl(self, *args, **kwargs)
   1516     return self._compiled_call_impl(*args, **kwargs)  # type: ignore[misc]
   1517 else:
-> 1518     return self._call_impl(*args, **kwargs)

File /opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py:1527, in Module._call_impl(self, *args, **kwargs)
   1522 # If we don't have any hooks, we want to skip the rest of the logic in
   1523 # this function, and just call forward.
   1524 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks
   1525         or _global_backward_pre_hooks or _global_backward_hooks
   1526         or _global_forward_hooks or _global_forward_pre_hooks):
-> 1527     return forward_call(*args, **kwargs)
   1529 try:
   1530     result = None

Cell In[204], line 25, in SimpleNN.forward(self, X)
     24 def forward(self, X):
---> 25     x = self.dense(X)
     26     output = torch.sigmoid(x)
     27     return output

File /opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py:1518, in Module._wrapped_call_impl(self, *args, **kwargs)
   1516     return self._compiled_call_impl(*args, **kwargs)  # type: ignore[misc]
   1517 else:
-> 1518     return self._call_impl(*args, **kwargs)

File /opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py:1527, in Module._call_impl(self, *args, **kwargs)
   1522 # If we don't have any hooks, we want to skip the rest of the logic in
   1523 # this function, and just call forward.
   1524 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks
   1525         or _global_backward_pre_hooks or _global_backward_hooks
   1526         or _global_forward_hooks or _global_forward_pre_hooks):
-> 1527     return forward_call(*args, **kwargs)
   1529 try:
   1530     result = None

File /opt/conda/lib/python3.10/site-packages/torch/nn/modules/container.py:215, in Sequential.forward(self, input)
    213 def forward(self, input):
    214     for module in self:
--> 215         input = module(input)
    216     return input

File /opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py:1518, in Module._wrapped_call_impl(self, *args, **kwargs)
   1516     return self._compiled_call_impl(*args, **kwargs)  # type: ignore[misc]
   1517 else:
-> 1518     return self._call_impl(*args, **kwargs)

File /opt/conda/lib/python3.10/site-packages/torch/nn/modules/module.py:1527, in Module._call_impl(self, *args, **kwargs)
   1522 # If we don't have any hooks, we want to skip the rest of the logic in
   1523 # this function, and just call forward.
   1524 if not (self._backward_hooks or self._backward_pre_hooks or self._forward_hooks or self._forward_pre_hooks
   1525         or _global_backward_pre_hooks or _global_backward_hooks
   1526         or _global_forward_hooks or _global_forward_pre_hooks):
-> 1527     return forward_call(*args, **kwargs)
   1529 try:
   1530     result = None

File /opt/conda/lib/python3.10/site-packages/torch/nn/modules/linear.py:114, in Linear.forward(self, input)
    113 def forward(self, input: Tensor) -> Tensor:
--> 114     return F.linear(input, self.weight, self.bias)

RuntimeError: mat1 and mat2 shapes cannot be multiplied (99x12 and 5x128)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-20 18:13:38 | 显示全部楼层
Terence888 发表于 2024-10-20 18:13
-------------------------------------------------- ...


这个错误是由输入张量的形状与网络的第一个全连接层的输入形状不匹配引起的。你的网络期望输入形状是 `(batch_size, 5)`,但实际提供的张量形状可能是 `(batch_size, 12)`。此问题通常发生于数据预处理阶段,输入数据维度没有正确处理。

这里有解决此问题的几个步骤:

1. **确认数据维度**:
   - 检查 `X_train`、`X_valid` 的形状是否正确。可以在传递给模型之前打印这些数据以确认其维度。

print(X_train.shape)
   print(X_valid.shape)

2. **确保输入层维度正确**:
   - 如果 `X_train` 和 `X_valid` 确实应该有 12 个特征,那么首层的输入维度需要与之匹配。修改 `SimpleNN` 初始化部分 `nn.Linear` 合适的输入维度:

self.dense = nn.Sequential(
       nn.Flatten(),
       nn.Linear(12, 128),  # 改为 12 而不是 5
       nn.ReLU(),  
       nn.Dropout(dropout1),
       nn.Linear(128, 256),
       nn.ReLU(),  
       nn.Dropout(dropout2),
       nn.Linear(256, 1),
   )

3. **修正数据预处理**:
   - 如果你的数据设计应是 5 个特征,检查数据是否在处理和整理期间增加了额外的列,比如由于拼接数据集或其他操作。

通过上述方法检查和修正后,应该能解决当前的问题。确保输入数据的维度和网络结构匹配始终是非常重要的操作步骤。

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

使用道具 举报

 楼主| 发表于 2024-10-20 18:58:14 | 显示全部楼层
FishC 发表于 2024-10-20 18:13
这个错误是由输入张量的形状与网络的第一个全连接层的输入形状不匹配引起的。你的网络期望输入形状是 ` ...
#使用dnn模型
import torch 
import torch.nn as nn
from torch.utils import data
from torch.utils.data import DataLoader
from torch import optim

#定义神经网络模型
dropout1, dropout2 = 0.2, 0.5
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.01)#定义优化器

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

#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):#slice不能直接用于Series和Dataframe,pandas中需要用.iloc或 .loc作为索引下标
        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:end], 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 #该四个数据类型为dataframe

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


for i in range(k):
    X_train,y_train, X_valid,y_valid = get_k_fold_data(k, i, X, y)  #获取第k折的训练集和验证集
    print(f'FOLD {i}')
    print('--------------------------------')
    # 将数据转换为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 = data.DataLoader(train_dataset, batch_size, shuffle=True)
    valid_iter = data.DataLoader(valid_dataset, batch_size, shuffle=True)
    
    #开始迭代
    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)
            train_accuracy = num_right / len(train_iter)

        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)
            valid_accuracy = num_right / len(valid_iter)
        
            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)))
模型训练代码如上,结果如下,如何调参
FOLD 0
--------------------------------
Loss: 6.226683553860144 Accuracy: 66.16666666666667 Epoch:0
Valid Loss: 38.41833853721619 Accuracy: 56.5 Epoch:0
Loss: 3.5451836194814312 Accuracy: 84.5 Epoch:200
Valid Loss: 126.12521135807037 Accuracy: 52.5 Epoch:200
Loss: 2.816117864142367 Accuracy: 86.66666666666667 Epoch:400
Valid Loss: 256.3632605969906 Accuracy: 52.0 Epoch:400
Loss: 3.308027188512094 Accuracy: 86.66666666666667 Epoch:600
Valid Loss: 326.8197889328003 Accuracy: 52.0 Epoch:600
Loss: 3.7842953309508753 Accuracy: 85.16666666666667 Epoch:800
Valid Loss: 410.2871125936508 Accuracy: 50.0 Epoch:800
FOLD 1
--------------------------------
Loss: 4.685332073105706 Accuracy: 84.33333333333333 Epoch:0
Valid Loss: 20.498585633933544 Accuracy: 64.0 Epoch:0
Loss: 3.03651670406768 Accuracy: 86.66666666666667 Epoch:200
Valid Loss: 117.32728180289268 Accuracy: 56.0 Epoch:200
Loss: 2.9526254301632027 Accuracy: 87.66666666666667 Epoch:400
Valid Loss: 165.77170491218567 Accuracy: 56.5 Epoch:400
Loss: 3.1301495668788752 Accuracy: 87.5 Epoch:600
Valid Loss: 228.67269039154053 Accuracy: 55.5 Epoch:600
Loss: 3.3299991672910334 Accuracy: 85.0 Epoch:800
Valid Loss: 311.4437175989151 Accuracy: 56.5 Epoch:800
FOLD 2
--------------------------------
Loss: 15.835803288357035 Accuracy: 83.5 Epoch:0
Valid Loss: 12.203755378723145 Accuracy: 67.5 Epoch:0
Loss: 2.5741791993690035 Accuracy: 86.83333333333333 Epoch:200
Valid Loss: 90.87414456903934 Accuracy: 60.5 Epoch:200
Loss: 3.1893928408231815 Accuracy: 85.83333333333333 Epoch:400
Valid Loss: 105.7586919516325 Accuracy: 57.5 Epoch:400
Loss: 3.273556094426938 Accuracy: 87.5 Epoch:600
Valid Loss: 99.86627879738808 Accuracy: 59.0 Epoch:600
Loss: 3.4933463196574857 Accuracy: 86.33333333333333 Epoch:800
Valid Loss: 95.46041409671307 Accuracy: 60.0 Epoch:800
FOLD 3
--------------------------------
Loss: 7.861726004227904 Accuracy: 83.5 Epoch:0
Valid Loss: 10.470404174178839 Accuracy: 66.5 Epoch:0
Loss: 3.109000958577029 Accuracy: 86.33333333333333 Epoch:200
Valid Loss: 91.99806115031242 Accuracy: 59.5 Epoch:200
Loss: 2.167286813293618 Accuracy: 87.5 Epoch:400
Valid Loss: 79.75543966889381 Accuracy: 58.0 Epoch:400
Loss: 3.834086375486359 Accuracy: 85.66666666666667 Epoch:600
Valid Loss: 105.04189059138298 Accuracy: 57.5 Epoch:600
Loss: 4.40276253007979 Accuracy: 87.83333333333333 Epoch:800
Valid Loss: 270.4698430299759 Accuracy: 57.0 Epoch:800
FOLD 4
--------------------------------
Loss: 24.082893710646687 Accuracy: 83.5 Epoch:0
Valid Loss: 11.500950686633587 Accuracy: 66.5 Epoch:0
Loss: 3.4417851725363255 Accuracy: 85.66666666666667 Epoch:200
Valid Loss: 18.1150611191988 Accuracy: 64.0 Epoch:200
Loss: 3.855657180199215 Accuracy: 85.33333333333333 Epoch:400
Valid Loss: 22.657909139990807 Accuracy: 63.5 Epoch:400
Loss: 2.762138690954695 Accuracy: 85.66666666666667 Epoch:600
Valid Loss: 126.66122741997242 Accuracy: 61.5 Epoch:600
Loss: 3.069612013118595 Accuracy: 85.16666666666667 Epoch:800
Valid Loss: 77.15786589682102 Accuracy: 61.5 Epoch:800
Training Ended
Average Loss: 192.91822670400143 Average Accuracy: 57.2
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-20 18:58:22 | 显示全部楼层
Terence888 发表于 2024-10-20 18:58
#使用dnn模型
import torch
import torch.nn as nn ...


从训练结果来看,训练集的正确率较高,但验证集的正确率和损失并没有明显的提升,这可能表明模型存在过拟合问题。过拟合通常是因为模型在训练集上表现很好,但是在验证集上的推广能力不足。以下是一些调参建议:

1. **降低学习率**:
   - 当前学习率为0.01,可能过高。尝试降低学习率,例如0.001或0.0001,这可以帮助模型在更新权重时更加稳定。

optimizer = optim.Adam(nn_model.parameters(), lr=0.001)  # 或者更小

2. **增加正则化**:
   - 使用更高的 `dropout` 比例可有效减少过拟合。在一定范围内(例如 `dropout1 = 0.3, dropout2 = 0.6`),尝试增大 dropout 的比率以减少过拟合。

3. **减少网络复杂度**:
   - 如果你的数据集较小,或者特征不够复杂,考虑减少网络层的节点数,例如 `nn.Linear(12, 64)` 和 `nn.Linear(64, 128)`。

4. **增强数据**:
   - 如果可能的话,尝试进行数据增强,通过生成更多样本来提高模型的鲁棒性。这种方法仅可用于图像或其他可转换类型数据。

5. **提前停止训练**:
   - 监控验证损失,如果验证损失在若干个 epoch 后不再减少,提前停止训练以防止过拟合。

6. **增加batch size**:
   - 尝试增大或缩小批量大小,如 `batch_size` 改为 32 或 64,找一个合适的值能提高模型的表现。

7. **使用不同的优化器**:
   - 尝试不同的优化器,比如 `SGD` 或 `RMSprop`,有时候可能改善性能,尤其是在训练不稳定时。

8. **调整损失函数**:
   - 确保损失函数选择合适,针对二元分类, `BCELoss` 是适合的。但如果标签有不均衡,可以考虑 `BCEWithLogitsLoss` 并设置 `pos_weight` 参数。

最后,每次更改参数时只有一个,以此观察其具体影响,改进训练结果。

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

使用道具 举报

 楼主| 发表于 2024-10-20 22:04:15 | 显示全部楼层
FishC 发表于 2024-10-20 18:58
从训练结果来看,训练集的正确率较高,但验证集的正确率和损失并没有明显的提升,这可能表明模型存在过 ...
FOLD 0
--------------------------------
Loss: 60.186356895499756 Accuracy: 84.33333333333333 Epoch:0
Valid Loss: 99.42159807682037 Accuracy: 69.0 Epoch:0
Loss: 34.96505515663712 Accuracy: 154.33333333333334 Epoch:200
Valid Loss: 70.55541038513184 Accuracy: 113.0 Epoch:200
Loss: 34.26509264553035 Accuracy: 160.0 Epoch:400
Valid Loss: 71.7145105600357 Accuracy: 104.0 Epoch:400
Loss: 36.23798611980897 Accuracy: 160.0 Epoch:600
Valid Loss: 74.42865025997162 Accuracy: 110.0 Epoch:600
Loss: 30.760017795695195 Accuracy: 157.66666666666666 Epoch:800
Valid Loss: 72.22203743457794 Accuracy: 111.0 Epoch:800

增加了批量大小,accuracy为什么超过100%了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-20 22:11:09 | 显示全部楼层
Terence888 发表于 2024-10-20 22:04
FOLD 0
--------------------------------
Loss: 60 ...


训练准确率超过100%通常是因为计算准确率时出现了问题。准确率通常是介于0到1(或百分比0到100之间)的一个值,超出很可能是相关代码有问题。以下是几个可能导致该问题的原因,以及排查思路:

1. **计算公式的问题**:
    - 确保计算准确率时,分母是正确的,即分母应该总是样本的数量。观察代码:"num_right / len(train_iter)"中的分母应为完整数据集样本数。
    - 需要用`len(train_iter.dataset)`来获取数据集的样本总数。

2. **累积误差**:
    - 如果累加了计算精度,而不是在每个epoch初始化计数器 `num_right` 和 `train_loss`,它可能导致错误。确保这两个变量在每次epoch开始时被重置。

3. **检查预测逻辑**:
    - 确保逻辑操作中的 `result` 是合理的,比如通过 `(pre_train > 0.5).numpy()` 做二分类。需要将预测值与实际标签比较,以获取正确预测的数量。

4. **数据问题**:
    - 确保你的数据迭代器没有重复计算或者数据没有被某种方式动态扩展。

请确保准确率是这样计算的:
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)
    train_l.backward()
    optimizer.step()

    train_loss += train_l.item() * len(tensor_x)
    result = (pre_train > 0.5).numpy()  # 转换为二进制预测
    num_right += np.sum(result.flatten() == tensor_y.flatten().numpy())

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

通过确保计算准确率的过程准确,应该能解决显示超过100%的问题。

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

使用道具 举报

 楼主| 发表于 2024-10-20 22:18:19 | 显示全部楼层
FishC 发表于 2024-10-20 22:11
训练准确率超过100%通常是因为计算准确率时出现了问题。准确率通常是介于0到1(或百分比0到100之间)的 ...

为什么
 len(train_iter)
不可以?train_iter是什么数据类型
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-20 22:18:26 | 显示全部楼层
Terence888 发表于 2024-10-20 22:18
为什么 len(train_iter)不可以?train_iter是什么数据 ...


`train_iter` 是通过 `DataLoader` 生成的一个可迭代对象,用于批量生成训练数据。在 PyTorch 中,`DataLoader` 会根据批量大小(`batch_size`)和数据集大小自动生成数据批次。

### 为什么使用 `len(train_iter)` 可能存在错误:

1. **`len(train_iter)` 返回批次数**:
   - `train_iter` 中的 `len(train_iter)` 返回的是批次的数量,而不是整个数据集的样本数量。假如有 1000 个样本,批量大小为 100,`len(train_iter)` 返回 10。
   - 如果使用 `len(train_iter)` 计算准确率,那么分母是批次数而不是样本数,导致准确率错误。

2. **准确率的计算需要样本总数**:
   - 在计算准确率时,应该使用数据集的总样本数而非批次数。正确的计算应该是使用 `len(train_iter.dataset)` 来获取数据集的大小。

### 使用 `DataLoader` 的正确方式:

- `DataLoader` 的工作方式是为模型提供各种小批量数据,用来在每个epoch期间迭代。
- 实际上,`train_iter` 本质上是一个 Python 的生成器或者可迭代对象,用于批量生成数据。

### 正确计算准确率的例子:
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)
    train_l.backward()
    optimizer.step()

    train_loss += train_l.item() * len(tensor_x)
    result = (pre_train > 0.5).numpy()
    num_right += np.sum(result == tensor_y.numpy().reshape(-1))

# 计算损失和准确率时使用数据集总数
train_loss = train_loss / len(train_iter.dataset)
train_accuracy = num_right / len(train_iter.dataset)

通过在 `len(train_iter.dataset)` 中使用数据集总样本数来正确地计算准确率,你将避免由于分母错误而导致的准确率超过100%的问题。

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

使用道具 举报

 楼主| 发表于 2024-10-22 00:18:52 | 显示全部楼层
FishC 发表于 2024-10-20 22:18
`train_iter` 是通过 `DataLoader` 生成的一个可迭代对象,用于批量生成训练数据。在 PyTorch 中,`Dat ...

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[24], line 82
     79 print('--------------------------------')
     81 #创建数据集
---> 82 train_dataset = SimpleDataset(X_train,y_train)
     83 valid_dataset = SimpleDataset(X_valid,y_valid)
     85 # 获取一个数据迭代器

TypeError: SimpleDataset.__init__() takes 1 positional argument but 3 were given
代码如下
#使用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

#定义数据集
class SimpleDataset(Dataset):
    def __init__(self):
        # Initialize data, download, etc.
        self.x = x
        self.y = y
    # support indexing such that dataset[i] can be used to get i-th sample
    def __getitem__(self, index):
        return self.x[index], self.y[index]

    # we can call len(dataset) to return the size
    def __len__(self):
        return len(self.x)

    
#初始化模型和优化器
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 = X.shape[0] // k
    X_train, y_train = None, None
    for j in range(k):#slice不能直接用于Series和Dataframe,pandas中需要用.iloc或 .loc作为索引下标
        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:end], 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 #该四个数据类型为dataframe


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

for i in range(k):
    X_train,y_train, X_valid,y_valid = get_k_fold_data(k, i, X, y)  #获取第k折的训练集和验证集
    print(f'FOLD {i}')
    print('--------------------------------')
    
    #创建数据集
    train_dataset = SimpleDataset(X_train,y_train)
    valid_dataset = SimpleDataset(X_valid,y_valid)

    # 获取一个数据迭代器
    train_iter = DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True,num_workers=2)
    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)))
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-22 00:30:34 | 显示全部楼层
Terence888 发表于 2024-10-22 00:18
-------------------------------------------------- ...


这个错误表明你定义的 `SimpleDataset` 类的 `__init__` 方法不接受除了 `self` 之外的额外参数,但你在实例化时传递了两个参数 (`X_train` 和 `y_train`)。需要确保 `__init__` 方法正确地接收这些参数。

为了修复这个问题,确保你的 `SimpleDataset` 定义如下:
class SimpleDataset(data.Dataset):
    def __init__(self, X, y):
        self.X = X
        self.y = y
    
    def __len__(self):
        return len(self.X)

    def __getitem__(self, idx):
        return self.X[idx], self.y[idx]

这样可以确保 `SimpleDataset` 正确地接收两个参数 `X` 和 `y`,并可以用于数据加载。

确认之后,再次通过如下代码初始化数据集:
# 创建数据集
train_dataset = SimpleDataset(X_train, y_train)
valid_dataset = SimpleDataset(X_valid, y_valid)

通过这种方式,传递给 `SimpleDataset` 的参数是被 `__init__` 方法正确处理的。

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

使用道具 举报

 楼主| 发表于 2024-10-22 00:38:00 | 显示全部楼层
FishC 发表于 2024-10-22 00:30
这个错误表明你定义的 `SimpleDataset` 类的 `__init__` 方法不接受除了 `self` 之外的额外参数,但你 ...
Fitting 5 folds for each of 40 candidates, totalling 200 fits
/opt/conda/lib/python3.10/site-packages/sklearn/base.py:432: UserWarning: X has feature names, but GradientBoostingClassifier was fitted without feature names
  warnings.warn(
---------------------------------------------------------------------------
NotFittedError                            Traceback (most recent call last)
Cell In[25], line 12
     10 gbc_grid = GridSearchCV(gbc, param_test, cv=5, refit=True, verbose=1)
     11 gbc_grid.fit(X_train,y_train)
---> 12 train_score = gbc.score(X_train,y_train)
     13 gbc_pre = gbc.predict(X_valid)
     14 valid_score = accuracy_score(y_valid,gbc_pre)

File /opt/conda/lib/python3.10/site-packages/sklearn/base.py:668, in ClassifierMixin.score(self, X, y, sample_weight)
    643 """
    644 Return the mean accuracy on the given test data and labels.
    645 
   (...)
    664     Mean accuracy of ``self.predict(X)`` w.r.t. `y`.
    665 """
    666 from .metrics import accuracy_score
--> 668 return accuracy_score(y, self.predict(X), sample_weight=sample_weight)

File /opt/conda/lib/python3.10/site-packages/sklearn/ensemble/_gb.py:1308, in GradientBoostingClassifier.predict(self, X)
   1293 def predict(self, X):
   1294     """Predict class for X.
   1295 
   1296     Parameters
   (...)
   1306         The predicted values.
   1307     """
-> 1308     raw_predictions = self.decision_function(X)
   1309     encoded_labels = self._loss._raw_prediction_to_decision(raw_predictions)
   1310     return self.classes_.take(encoded_labels, axis=0)

File /opt/conda/lib/python3.10/site-packages/sklearn/ensemble/_gb.py:1264, in GradientBoostingClassifier.decision_function(self, X)
   1243 """Compute the decision function of ``X``.
   1244 
   1245 Parameters
   (...)
   1259     array of shape (n_samples,).
   1260 """
   1261 X = self._validate_data(
   1262     X, dtype=DTYPE, order="C", accept_sparse="csr", reset=False
   1263 )
-> 1264 raw_predictions = self._raw_predict(X)
   1265 if raw_predictions.shape[1] == 1:
   1266     return raw_predictions.ravel()

File /opt/conda/lib/python3.10/site-packages/sklearn/ensemble/_gb.py:687, in BaseGradientBoosting._raw_predict(self, X)
    685 def _raw_predict(self, X):
    686     """Return the sum of the trees raw predictions (+ init estimator)."""
--> 687     raw_predictions = self._raw_predict_init(X)
    688     predict_stages(self.estimators_, X, self.learning_rate, raw_predictions)
    689     return raw_predictions

File /opt/conda/lib/python3.10/site-packages/sklearn/ensemble/_gb.py:673, in BaseGradientBoosting._raw_predict_init(self, X)
    671 def _raw_predict_init(self, X):
    672     """Check input and compute raw predictions of the init estimator."""
--> 673     self._check_initialized()
    674     X = self.estimators_[0, 0]._validate_X_predict(X, check_input=True)
    675     if self.init_ == "zero":

File /opt/conda/lib/python3.10/site-packages/sklearn/ensemble/_gb.py:382, in BaseGradientBoosting._check_initialized(self)
    380 def _check_initialized(self):
    381     """Check that the estimator is initialized, raising an error if not."""
--> 382     check_is_fitted(self)

File /opt/conda/lib/python3.10/site-packages/sklearn/utils/validation.py:1390, in check_is_fitted(estimator, attributes, msg, all_or_any)
   1385     fitted = [
   1386         v for v in vars(estimator) if v.endswith("_") and not v.startswith("__")
   1387     ]
   1389 if not fitted:
-> 1390     raise NotFittedError(msg % {"name": type(estimator).__name__})

NotFittedError: This GradientBoostingClassifier instance is not fitted yet. Call 'fit' with appropriate arguments before using this estimator.
训练模型时报错,代码如下
#使用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

#定义数据集
class SimpleDataset(Dataset):
    def __init__(self,X,y):
        # Initialize data, download, etc.
        self.X = X
        self.y = y
    # support indexing such that dataset[i] can be used to get i-th sample
    def __getitem__(self, index):
        return self.X[index], self.y[index]

    # we can call len(dataset) to return the size
    def __len__(self):
        return len(self.X)

    
#初始化模型和优化器
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 = X.shape[0] // k
    X_train, y_train = None, None
    for j in range(k):#slice不能直接用于Series和Dataframe,pandas中需要用.iloc或 .loc作为索引下标
        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:end], 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 #该四个数据类型为dataframe


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

for i in range(k):
    X_train,y_train, X_valid,y_valid = get_k_fold_data(k, i, X, y)  #获取第k折的训练集和验证集
    print(f'FOLD {i}')
    print('--------------------------------')
    
    #创建数据集
    train_dataset = SimpleDataset(X_train,y_train)
    valid_dataset = SimpleDataset(X_valid,y_valid)

    # 获取一个数据迭代器
    train_iter = DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True,num_workers=2)
    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)))
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-22 00:38:16 | 显示全部楼层
Terence888 发表于 2024-10-22 00:38
Fitting 5 folds for each of 40 candidates, totalli ...


您提到的错误是关于 `GradientBoostingClassifier` 而不是 PyTorch 的神经网络。这表明代码中可能有多个模型在使用,包括 Scikit-learn 的 `GradientBoostingClassifier`。让我们探讨一些导致该错误的常见原因,以及如何修复这些错误:

### 问题分析与解决方案

#### 1. **未正确调用`fit`方法:**
   - 确保你在 `GradientBoostingClassifier` 上调用了 `fit`。
   - `fit` 方法应该使用训练数据来训练模型,而 `NotFittedError` 表示在`fit`之前尝试使用模型进行预测或评估。

#### 2. **使用错误的变量名称:**
   - 单步检查一下您对`gbc`的调用——确保您在调用`.fit()`和后续的`.score()`时都是在使用正确的对象名。

#### 示例修正
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score
import numpy as np

# 假装的特征集和标签集
X_train = ...
y_train = ...
X_valid = ...
y_valid = ...

# 设置参数
param_test = {
    'n_estimators': [100, 200],
    'max_depth': [3, 4, 5],
}

gbc = GradientBoostingClassifier()

# 创建网格搜索
gbc_grid = GridSearchCV(estimator=gbc, param_grid=param_test, cv=5, verbose=1)

# 调用fit方法
gbc_grid.fit(X_train, y_train)

# 检查score
train_score = gbc_grid.score(X_train, y_train)
print(f"Train score: {train_score}")

# 验证
gbc_pre = gbc_grid.predict(X_valid)
valid_score = accuracy_score(y_valid, gbc_pre)
print(f"Validation score: {valid_score}")
#### 3. **确保使用一致的特征集:**
   - 您可能因为特征名称不匹配的警告而遇到问题。请确保在训练和测试时使用的数据特征完整一致。

如果问题仍然无法解决,请确保没有遗漏别的代码片段和实现步骤,因为更改上下文可能引入新的问题。任何进一步的调试都将基于更多关于数据和其它相关代码的详细信息。

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

使用道具 举报

 楼主| 发表于 2024-10-22 00:48:04 | 显示全部楼层
FishC 发表于 2024-10-22 00:38
您提到的错误是关于 `GradientBoostingClassifier` 而不是 PyTorch 的神经网络。这表明代码中可能有多 ...
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[43], line 93
     91 train_loss = 0
     92 num_right = 0
---> 93 for tensor_x, tensor_y in train_iter:#训练集执行梯度更新
     94     tensor_x = tensor_x.float()
     95     tensor_y = tensor_y.float().reshape(-1, 1)

File /opt/conda/lib/python3.10/site-packages/torch/utils/data/dataloader.py:630, in _BaseDataLoaderIter.__next__(self)
    627 if self._sampler_iter is None:
    628     # TODO(https://github.com/pytorch/pytorch/issues/76750)
    629     self._reset()  # type: ignore[call-arg]
--> 630 data = self._next_data()
    631 self._num_yielded += 1
    632 if self._dataset_kind == _DatasetKind.Iterable and \
    633         self._IterableDataset_len_called is not None and \
    634         self._num_yielded > self._IterableDataset_len_called:

File /opt/conda/lib/python3.10/site-packages/torch/utils/data/dataloader.py:1345, in _MultiProcessingDataLoaderIter._next_data(self)
   1343 else:
   1344     del self._task_info[idx]
-> 1345     return self._process_data(data)

File /opt/conda/lib/python3.10/site-packages/torch/utils/data/dataloader.py:1371, in _MultiProcessingDataLoaderIter._process_data(self, data)
   1369 self._try_put_index()
   1370 if isinstance(data, ExceptionWrapper):
-> 1371     data.reraise()
   1372 return data

File /opt/conda/lib/python3.10/site-packages/torch/_utils.py:694, in ExceptionWrapper.reraise(self)
    690 except TypeError:
    691     # If the exception takes multiple arguments, don't try to
    692     # instantiate since we don't know how to
    693     raise RuntimeError(msg) from None
--> 694 raise exception

KeyError: Caught KeyError in DataLoader worker process 0.
Original Traceback (most recent call last):
  File "/opt/conda/lib/python3.10/site-packages/pandas/core/indexes/base.py", line 3805, in get_loc
    return self._engine.get_loc(casted_key)
  File "index.pyx", line 167, in pandas._libs.index.IndexEngine.get_loc
  File "index.pyx", line 196, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/hashtable_class_helper.pxi", line 7081, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas/_libs/hashtable_class_helper.pxi", line 7089, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: 392

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/conda/lib/python3.10/site-packages/torch/utils/data/_utils/worker.py", line 308, in _worker_loop
    data = fetcher.fetch(index)
  File "/opt/conda/lib/python3.10/site-packages/torch/utils/data/_utils/fetch.py", line 51, in fetch
    data = [self.dataset[idx] for idx in possibly_batched_index]
  File "/opt/conda/lib/python3.10/site-packages/torch/utils/data/_utils/fetch.py", line 51, in <listcomp>
    data = [self.dataset[idx] for idx in possibly_batched_index]
  File "/tmp/ipykernel_33/1733971443.py", line 37, in __getitem__
    return self.X[index], self.y[index]
  File "/opt/conda/lib/python3.10/site-packages/pandas/core/frame.py", line 4102, in __getitem__
    indexer = self.columns.get_loc(key)
  File "/opt/conda/lib/python3.10/site-packages/pandas/core/indexes/base.py", line 3812, in get_loc
    raise KeyError(key) from err
KeyError: 392
add Code
还是报错
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-10-22 01:14:01 | 显示全部楼层
FishC 发表于 2024-10-22 00:38
您提到的错误是关于 `GradientBoostingClassifier` 而不是 PyTorch 的神经网络。这表明代码中可能有多 ...

dnn模型训练代码
#使用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

#定义数据集
class SimpleDataset(Dataset):
    def __init__(self,X,y):
        # Initialize data, download, etc.
        self.X = X
        self.y = y
    # support indexing such that dataset[i] can be used to get i-th sample
    def __getitem__(self, index):
        return self.X[index], self.y[index]

    # we can call len(dataset) to return the size
    def __len__(self):
        return len(self.X)

    
#初始化模型和优化器
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 = X.shape[0] // k
    X_train, y_train = None, None
    for j in range(k):#slice不能直接用于Series和Dataframe,pandas中需要用.iloc或 .loc作为索引下标
        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:end], 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 #该四个数据类型为dataframe


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

for i in range(k):
    X_train,y_train, X_valid,y_valid = get_k_fold_data(k, i, X, y)  #获取第k折的训练集和验证集
    print(f'FOLD {i}')
    print('--------------------------------')
    
    #创建数据集
    train_dataset = SimpleDataset(X_train,y_train)
    valid_dataset = SimpleDataset(X_valid,y_valid)

    # 获取一个数据迭代器
    train_iter = DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True,num_workers=2)
    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)))

报错:
FOLD 0
--------------------------------
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[43], line 93
     91 train_loss = 0
     92 num_right = 0
---> 93 for tensor_x, tensor_y in train_iter:#训练集执行梯度更新
     94     tensor_x = tensor_x.float()
     95     tensor_y = tensor_y.float().reshape(-1, 1)

File /opt/conda/lib/python3.10/site-packages/torch/utils/data/dataloader.py:630, in _BaseDataLoaderIter.__next__(self)
    627 if self._sampler_iter is None:
    628     # TODO(https://github.com/pytorch/pytorch/issues/76750)
    629     self._reset()  # type: ignore[call-arg]
--> 630 data = self._next_data()
    631 self._num_yielded += 1
    632 if self._dataset_kind == _DatasetKind.Iterable and \
    633         self._IterableDataset_len_called is not None and \
    634         self._num_yielded > self._IterableDataset_len_called:

File /opt/conda/lib/python3.10/site-packages/torch/utils/data/dataloader.py:1345, in _MultiProcessingDataLoaderIter._next_data(self)
   1343 else:
   1344     del self._task_info[idx]
-> 1345     return self._process_data(data)

File /opt/conda/lib/python3.10/site-packages/torch/utils/data/dataloader.py:1371, in _MultiProcessingDataLoaderIter._process_data(self, data)
   1369 self._try_put_index()
   1370 if isinstance(data, ExceptionWrapper):
-> 1371     data.reraise()
   1372 return data

File /opt/conda/lib/python3.10/site-packages/torch/_utils.py:694, in ExceptionWrapper.reraise(self)
    690 except TypeError:
    691     # If the exception takes multiple arguments, don't try to
    692     # instantiate since we don't know how to
    693     raise RuntimeError(msg) from None
--> 694 raise exception

KeyError: Caught KeyError in DataLoader worker process 0.
Original Traceback (most recent call last):
  File "/opt/conda/lib/python3.10/site-packages/pandas/core/indexes/base.py", line 3805, in get_loc
    return self._engine.get_loc(casted_key)
  File "index.pyx", line 167, in pandas._libs.index.IndexEngine.get_loc
  File "index.pyx", line 196, in pandas._libs.index.IndexEngine.get_loc
  File "pandas/_libs/hashtable_class_helper.pxi", line 7081, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas/_libs/hashtable_class_helper.pxi", line 7089, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: 392

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/conda/lib/python3.10/site-packages/torch/utils/data/_utils/worker.py", line 308, in _worker_loop
    data = fetcher.fetch(index)
  File "/opt/conda/lib/python3.10/site-packages/torch/utils/data/_utils/fetch.py", line 51, in fetch
    data = [self.dataset[idx] for idx in possibly_batched_index]
  File "/opt/conda/lib/python3.10/site-packages/torch/utils/data/_utils/fetch.py", line 51, in <listcomp>
    data = [self.dataset[idx] for idx in possibly_batched_index]
  File "/tmp/ipykernel_33/1733971443.py", line 37, in __getitem__
    return self.X[index], self.y[index]
  File "/opt/conda/lib/python3.10/site-packages/pandas/core/frame.py", line 4102, in __getitem__
    indexer = self.columns.get_loc(key)
  File "/opt/conda/lib/python3.10/site-packages/pandas/core/indexes/base.py", line 3812, in get_loc
    raise KeyError(key) from err
KeyError: 392
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-10-22 01:22:09 | 显示全部楼层
Terence888 发表于 2024-10-22 01:14
dnn模型训练代码#使用dnn模型
import torch
import ...


从提供的错误信息和代码来看,主要问题出现在自定义数据集 `SimpleDataset` 的 `__getitem__` 方法中。当前的实现未能正确返回数据集中的 `index` 项,而是企图返回整个数据集。

以下是您所需的更改和一些额外的优化建议:

### 1. 修正 SimpleDataset `__getitem__` 方法

在您的 `SimpleDataset` 类中,需要确保 `__getitem__` 返回的是指定 `index` 处的数据,而不是整个数据集:
class SimpleDataset(Dataset):
    def __init__(self, X, y):
        self.X = X
        self.y = y

    def __getitem__(self, index):
        # 返回X和y在指定index处的数据
        return self.X.iloc[index].values, self.y.iloc[index]

    def __len__(self):
        return len(self.X)

### 2. 验证 `get_k_fold_data` 方法

确保 `get_k_fold_data` 方法正确地返回了 DataFrame 对象的训练和验证集:
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

### 3. 初始化名单(变量)

确保 `acc_list` 和 `loss_list` 已成功初始化:
acc_list = []
loss_list = []

### 4. 验证运行环境

确保所有依赖库已按要求被安装和导入,包括 `pandas`、`torch`、`numpy` 等。如果代码仍出现错误,考虑在不同环境中运行测试,逐步排查可能的环境问题。

这应该能修复代码中的现有问题,同时确保按应有的数据索引来获取数据。如果进一步的错误依旧存,请提供更多信息进行更深度的调试。

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-21 20:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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