FishC 发表于 2024-10-20 11:21:23

Terence888 发表于 2024-10-20 11:13
with torch.no_grad():
            valid_loss = 0
...

在验证集上不执行梯度下降是深度学习中的常见做法。其原因和逻辑如下:

1. **评估模型性能**:验证集的主要目的在于评估模型的泛化性能,而不是用来更新模型参数。如果在验证集上进行了梯度下降,模型将会对验证集信息过拟合,无法提供客观的性能评估。

2. **避免信息泄露**:通过不更新模型参数,可以确保验证集保持独立性,从而使其评估过程不受训练集的影响。

3. **性能监控**:在训练过程中,不仅以训练损失作为评估标准,还可以用验证集的损失和准确率来监控模型表现。这可以在某种程度上避免过拟合,帮助选择合适的训练轮次(比如通过早停策略)。

4. ****:`torch.no_grad()`上下文管理器会临时关闭自动求导引擎,用于禁用梯度计算。这不但节省了计算资源,也节省了内存,因为不需要存储计算图相关信息。

在上面的代码片段中,`torch.no_grad()`用于括住验证步骤,确保在该阶段不进行梯度计算和参数更新。因此,验证集仅用于评估目的,而非训练,保持了其作为独立评估数据集的角色。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

Terence888 发表于 2024-10-20 11:52:49

FishC 发表于 2024-10-20 11:21
在验证集上不执行梯度下降是深度学习中的常见做法。其原因和逻辑如下:

1. **评估模型性能**:验证 ...

dropout1,dropout2 = 0.2,0.5
class SimpleNN(nn.Module):
    def __init__(self):
      super(dense,self).__init__()
      self.dense = nn.Sequential(nn.Flatten(),
      nn.Linear(5,128),
      nn.ReLu(),
      nn.Dropout(dropout1),#训练时,Dropout层将根据指定的暂退概率随机丢弃上一层的输出(相当于下一层的输入);测试时,Dropout层仅传递数据
      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

报错
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In, line 60
   57 loss = nn.BCELoss()
   59 #定义训练模型
---> 60 nn_model = SimpleNN()
   62 #定义优化器
   63 optimizer = optim.Adam(nn_model.parameters(),lr = 0.001)   

Cell In, line 13, in SimpleNN.__init__(self)
   12 def __init__(self):
---> 13   super(dense,self).__init__()
   14   self.dense = nn.Sequential(nn.Flatten(),
   15   nn.Linear(5,128),
   16   nn.ReLu(),
   (...)
   21   nn.Linear(256,1),
   22   )

NameError: name 'dense' is not defined

FishC 发表于 2024-10-20 11:53:01

Terence888 发表于 2024-10-20 11:52
dropout1,dropout2 = 0.2,0.5
class SimpleNN(nn.Mod ...

你这里的`NameError`是由于`super(dense, self).__init__()`中的`dense`未定义而引起的。`super()`函数的第一个参数应该是当前类的名称,`dense`并不是类名,而且并没有定义为一个变量。

下面是修正后的代码:

import torch
import torch.nn as nn

dropout1, dropout2 = 0.2, 0.5

class SimpleNN(nn.Module):
    def __init__(self):
      super(SimpleNN, self).__init__()# 修正: 这里需要用 SimpleNN 而不是 dense
      self.dense = nn.Sequential(
            nn.Flatten(),
            nn.Linear(5, 128),
            nn.ReLU(),# 修正: ReLu 改为 ReLU()
            nn.Dropout(dropout1),
            nn.Linear(128, 256),
            nn.ReLU(),# 修正: ReLu 改为 ReLU()
            nn.Dropout(dropout2),
            nn.Linear(256, 1),
      )
      
    def forward(self, X):
      x = self.dense(X)
      output = torch.sigmoid(x)
      return output

修正点:
1. **`super()`使用正确的类名**:你需要将`dense`换成当前类名`SimpleNN`。
2. **正确的激活函数**:应该是`nn.ReLU()`而不是`nn.ReLu()`,注意`ReLU`中"U"是大写。
3. **确保所有模块都正确导入**。通常需要导入`torch`、`torch.nn`,以及可能的`torch.optim`或其他模块。

以上调整后应该可以正确初始化你的`SimpleNN`模型实例。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

Terence888 发表于 2024-10-20 11:57:00

FishC 发表于 2024-10-20 11:53
你这里的`NameError`是由于`super(dense, self).__init__()`中的`dense`未定义而引起的。`super()`函数 ...

#开始训练
acc_list = []
loss_list = []
batch_size = 99
k = 5
num_epochs = 10000
for i in range(k):
    X_train,X_valid,y_train,y_valid = get_k_fold_data(k, i, X, y)#获取第k折的训练集和验证集
    print(f'FOLD {i}')
    print('--------------------------------')
    X_train = torch.tensor(X_train,dtype=float32)#将数据转化成张量
    y_train = torch.tensor(y_train,dtype=float32)
    X_valid = torch.tensor(X_valid,dtype=float32)
    y_valid = torch.tensor(y_valid,dtype=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)

报错如下
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In, line 75
   73 print(f'FOLD {i}')
   74 print('--------------------------------')
---> 75 X_train = torch.tensor(X_train,dtype=float32)#将数据转化成张量
   76 y_train = torch.tensor(y_train,dtype=float32)
   77 X_valid = torch.tensor(X_valid,dtype=float32)

NameError: name 'float32' is not defined

FishC 发表于 2024-10-20 11:57:07

Terence888 发表于 2024-10-20 11:57
#开始训练
acc_list =
loss_list =
batch_size = ...

出现 `NameError: name 'float32' is not defined` 错误,是因为在调用 `torch.tensor` 时,数据类型参数 `dtype` 应该使用 `torch.float32` 而不是 `float32`。`torch.float32` 是 PyTorch 中的浮点数数据类型标识符。

以下是如何修正这段代码:

import torch
from torch.utils import data

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

for i in range(k):
    X_train, X_valid, y_train, y_valid = get_k_fold_data(k, i, X, y)# 获取第k折的训练集和验证集
    print(f'FOLD {i}')
    print('--------------------------------')
    X_train = torch.tensor(X_train, dtype=torch.float32)# 将数据转化成张量
    y_train = torch.tensor(y_train, dtype=torch.float32)
    X_valid = torch.tensor(X_valid, dtype=torch.float32)
    y_valid = torch.tensor(y_valid, 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)

修正要点:
1. 使用 `torch.float32` 作为数据类型,而不是 `float32`。
2. 添加 `import torch` 和 `from torch.utils import data` 确保必要的模块已被正确导入。

此修正应能解决所报的错误,并正确地将数据转换为 PyTorch 张量。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

Terence888 发表于 2024-10-20 12:19:33

FishC 发表于 2024-10-20 11:57
出现 `NameError: name 'float32' is not defined` 错误,是因为在调用 `torch.tensor` 时,数据类型参 ...

---------------------------------------------------------------------------
ValueError                              Traceback (most recent call last)
Cell In, line 76
   74 print(f'FOLD {i}')
   75 print('--------------------------------')
---> 76 X_train = torch.tensor(X_train,dtype=torch.float32)#将数据转化成张量
   77 y_train = torch.tensor(y_train,dtype=torch.float32)
   78 X_valid = torch.tensor(X_valid,dtype=torch.float32)

ValueError: could not determine the shape of object type 'DataFrame'

修正后报错如上

FishC 发表于 2024-10-20 12:23:10

Terence888 发表于 2024-10-20 12:19
-------------------------------------------------- ...

出现这个错误是因为`torch.tensor`函数期望的输入是NumPy数组或类似的基础结构,而不能直接处理pandas的DataFrame对象。在将pandas DataFrame转换为PyTorch张量前,您需要先将它转换为NumPy数组。

可以通过以下方式修正代码:

import torch
from torch.utils import data

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

for i in range(k):
    X_train, X_valid, y_train, 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)

修正点:
1. **使用`.values`属性**:通过使用`.values`属性,可以将`pandas` DataFrame或Series转换为NumPy数组。
2. **空列表初始化**:确保`acc_list`和`loss_list`被初始化为空列表,以便用来存储训练过程中各个折的准确率和损失值。

这样的修改应该能解决错误并正确进行训练和验证数据的批量处理。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

Terence888 发表于 2024-10-20 15:50:43

FishC 发表于 2024-10-20 12:23
出现这个错误是因为`torch.tensor`函数期望的输入是NumPy数组或类似的基础结构,而不能直接处理pandas ...

获取第k折的训练集和验证集函数
def get_k_fold_data(k, i, X, y):
    assert k > 1
    fold_size = X.shape // 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, y
      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(, 0)
            y_train = torch.cat(, 0)
    return X_train, y_train, X_valid, y_valid
按k的顺序迭代
for i in range(k):
    X_train, X_valid, y_train, 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)

报错如下---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
File /opt/conda/lib/python3.10/site-packages/pandas/core/indexes/base.py:3805, in Index.get_loc(self, key)
   3804 try:
-> 3805   return self._engine.get_loc(casted_key)
   3806 except KeyError as err:

File index.pyx:167, in pandas._libs.index.IndexEngine.get_loc()

File index.pyx:173, in pandas._libs.index.IndexEngine.get_loc()

TypeError: '(slice(0, 142, None), slice(None, None, None))' is an invalid key

During handling of the above exception, another exception occurred:

InvalidIndexError                         Traceback (most recent call last)
Cell In, line 62
   59 nn_model = SimpleNN()
   61 for i in range(k):
---> 62   X_train, X_valid, y_train, y_valid = get_k_fold_data(k, i, X, y)#获取第k折的训练集和验证集
   63   print(f'FOLD {i}')
   64   print('--------------------------------')

Cell In, line 43, in get_k_fold_data(k, i, X, y)
   41 for j in range(k):
   42   idx = slice(j * fold_size, (j + 1) * fold_size)
---> 43   X_part, y_part = X, y
   44   if j == i:
   45         X_valid, y_valid = X_part, y_part

File /opt/conda/lib/python3.10/site-packages/pandas/core/frame.py:4102, in DataFrame.__getitem__(self, key)
   4100 if self.columns.nlevels > 1:
   4101   return self._getitem_multilevel(key)
-> 4102 indexer = self.columns.get_loc(key)
   4103 if is_integer(indexer):
   4104   indexer =

File /opt/conda/lib/python3.10/site-packages/pandas/core/indexes/base.py:3817, in Index.get_loc(self, key)
   3812   raise KeyError(key) from err
   3813 except TypeError:
   3814   # If we have a listlike key, _check_indexing_error will raise
   3815   #InvalidIndexError. Otherwise we fall through and re-raise
   3816   #the TypeError.
-> 3817   self._check_indexing_error(key)
   3818   raise

File /opt/conda/lib/python3.10/site-packages/pandas/core/indexes/base.py:6059, in Index._check_indexing_error(self, key)
   6055 def _check_indexing_error(self, key):
   6056   if not is_scalar(key):
   6057         # if key is not a scalar, directly raise an error (the code below
   6058         # would convert to numpy arrays and raise later any way) - GH29926
-> 6059         raise InvalidIndexError(key)

InvalidIndexError: (slice(0, 142, None), slice(None, None, None))

FishC 发表于 2024-10-20 15:50:51

Terence888 发表于 2024-10-20 15:50
获取第k折的训练集和验证集函数
def get_k_fold_data ...

这个错误表明您在尝试对 `pandas` DataFrame 进行切片操作时使用了无效的索引方式。这个问题的出现是因为您直接将 `slice` 对象应用于 `DataFrame` 或 `Series`,而在 Pandas 中需要使用 `.iloc` 或 `.loc` 进行行数据选择。

以下是修复您实现 `get_k_fold_data` 的方法:

def get_k_fold_data(k, i, X, y):
    assert k > 1
    fold_size = len(X) // k# 使用数组的长度而不是 X.shape
    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, y.iloc# 使用 .iloc 进行行选取
      elif X_train is None:
            X_train, y_train = X.iloc, y.iloc
      else:
            X_train = pd.concat(], ignore_index=True)
            y_train = pd.concat(], ignore_index=True)
    return X_train, y_train, X_valid, y_valid

# Rest of your code to use these functions goes here...

### 修改说明:

1. **`len(X)`而不是`X.shape`**:直接用`len(X)`获取样本的总数,以避免使用多维度不兼容的问题。

2. **使用`.iloc`进行行切片**:`.iloc`是Pandas提供的用于按照位置索引行的方式,这里适合您的应用场景。

3. **使用`pd.concat`连接DataFrames**:确保使用`pd.concat`逐折叠合您的训练集样本,同时设置`ignore_index=True`以确保返回的索引不重复/不乱序。

这段代码应该可以修复您在`get_k_fold_data`中遇到的问题。每一步都正确切分并合并了训练集和验证集。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

Terence888 发表于 2024-10-20 16:16:59

FishC 发表于 2024-10-20 15:50
这个错误表明您在尝试对 `pandas` DataFrame 进行切片操作时使用了无效的索引方式。这个问题的出现是因 ...

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In, line 66
   64 print('--------------------------------')
   65 # 将数据转换为NumPy数组,然后再转换为PyTorch张量
---> 66 X_train = torch.tensor(X_train.values, dtype=torch.float32)
   67 y_train = torch.tensor(y_train.values, dtype=torch.float32)
   68 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.

FishC 发表于 2024-10-20 16:23:21

Terence888 发表于 2024-10-20 16:16
-------------------------------------------------- ...

这个错误表示 `X_train.values` 的数据类型存在一些不是数值(比如 `nan`、字符串或者其他的对象类型),在尝试转换为 PyTorch 张量时出现了问题。为了修复这个问题,我们需要确保所有的数据都被转换为数值数据类型,如 `float64` 或 `float32`。以下是如何处理此问题的步骤:

1. **确保每个变量都是数值类型:**
   - 使用 `pandas.DataFrame.fillna()` 填充 `nan`。
   - 将 DataFrame 的所有列转换为浮点数。

2. **转换为 NumPy 数组后再转换为 PyTorch 张量:**

以下是修正您的代码:

import torch
from torch.utils import data

# 假设 get_k_fold_data 已经定义并正确返回 pandas 的 DataFrame 对象

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

for i in range(k):
    X_train, X_valid, y_train, y_valid = get_k_fold_data(k, i, X, y)
    print(f'FOLD {i}')
    print('--------------------------------')
   
    # 确保 X_train 和 y_train 中只有数值数据
    X_train = X_train.fillna(0).astype('float32')# 用0替代缺失值并确保是 float32 类型
    X_valid = X_valid.fillna(0).astype('float32')
    y_train = y_train.fillna(0).astype('float32')
    y_valid = y_valid.fillna(0).astype('float32')
   
    # 转换为 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=batch_size, shuffle=True)
    valid_iter = data.DataLoader(valid_dataset, batch_size=batch_size, shuffle=True)

### 修正说明
- **填充值**:`fillna(0)`用以替代任何缺失值(可以根据具体情况选择适当的填充值)。
- **数值类型转换**:使用 `.astype('float32')` 确保所有数据以适当的数值类型出现。

在这么做之后,`X_train.values` 应该会是一个只含数值类型的 `NumPy` 数组,从而允许正确地转换为 `PyTorch` 张量。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

Terence888 发表于 2024-10-20 16:34:28

FishC 发表于 2024-10-20 16:23
这个错误表示 `X_train.values` 的数据类型存在一些不是数值(比如 `nan`、字符串或者其他的对象类型) ...

#使用Decision Tree
from sklearn.tree import DecisionTreeClassifier
dt_model = DecisionTreeClassifier(criterion='entropy', random_state=1)
dt_model.fit(X_train,y_train)
DT_pre = dt_model.predict(X_valid)
num_right = np.sum(DT_pre == y_valid)
dt_valid_acc = num_right / len(X_valid)

使用决策树模型进行评估报错
---------------------------------------------------------------------------
ValueError                              Traceback (most recent call last)
Cell In, line 4
      2 from sklearn.tree import DecisionTreeClassifier
      3 dt_model = DecisionTreeClassifier(criterion='entropy', random_state=1)
----> 4 dt_model.fit(X_train,y_train)
      5 DT_pre = dt_model.predict(X_valid)
      6 num_right = np.sum(DT_pre == y_valid)

File /opt/conda/lib/python3.10/site-packages/sklearn/tree/_classes.py:889, in DecisionTreeClassifier.fit(self, X, y, sample_weight, check_input)
    859 def fit(self, X, y, sample_weight=None, check_input=True):
    860   """Build a decision tree classifier from the training set (X, y).
    861
    862   Parameters
   (...)
    886         Fitted estimator.
    887   """
--> 889   super().fit(
    890         X,
    891         y,
    892         sample_weight=sample_weight,
    893         check_input=check_input,
    894   )
    895   return self

File /opt/conda/lib/python3.10/site-packages/sklearn/tree/_classes.py:224, in BaseDecisionTree.fit(self, X, y, sample_weight, check_input)
    221 self.n_outputs_ = y.shape
    223 if is_classification:
--> 224   check_classification_targets(y)
    225   y = np.copy(y)
    227   self.classes_ = []

File /opt/conda/lib/python3.10/site-packages/sklearn/utils/multiclass.py:218, in check_classification_targets(y)
    210 y_type = type_of_target(y, input_name="y")
    211 if y_type not in [
    212   "binary",
    213   "multiclass",
   (...)
    216   "multilabel-sequences",
    217 ]:
--> 218   raise ValueError("Unknown label type: %r" % y_type)

ValueError: Unknown label type: 'continuous-multioutput'

FishC 发表于 2024-10-20 16:42:49

Terence888 发表于 2024-10-20 16:34
#使用Decision Tree
from sklearn.tree import Decis ...

这个错误表明,您的目标变量 `y_train` 不是被识别为时序或分类任务常用的二元或多类别标签,而是被认为是连续多输出的形式。这通常发生在您试图使用分类算法(如决策树分类器)而您的标签数据格式不正确的情况下。

解决方案:
1. **检查标签数据结构**:确保 `y_train` 是一个一维数组或 Series 而不是二维数组。如果它是一维数组而错误地被理解为多维结构,将其展平为一维。

2. **检验`y_train`内容并且确保是整数字符或是二进制值**:这种错误也可能因为 `y_train` 包含在回归问题上常见的连续数字(如动态范围的浮点数)而不是分类问题上常用的类别标签(比如0和1)。

以下是修正代码的步骤:

# 从pandas Series确保是NumPy一维数组
y_train_flat = y_train.values.ravel()# 展平(flatten)数据

# 同理对于验证集的y
y_valid_flat = y_valid.values.ravel()

# 训练模型
dt_model.fit(X_train, y_train_flat)

# 验证模型
DT_pre = dt_model.predict(X_valid)
num_right = np.sum(DT_pre == y_valid_flat)
dt_valid_acc = num_right / len(X_valid)

print(f"Decision Tree Validation Accuracy: {dt_valid_acc:.2f}")

### 说明:
- **`ravel()`** 将多维数组展平并返回一维数组,以保证标签的生成符合分类器的输入要求。
- 确保`y_train`和`y_valid`仅包含被分类类别的值(如整数形式的类别id或分类标签),而不是连续的数值。
- `DecisionTreeClassifier`用于分类问题,因此确保标签为离散类别。

这些步骤应有助于解决错误,并允许您用决策树模型进行分类任务的正确训练和评价。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: 1 [2]
查看完整版本: pytorch的nn模型训练数据