Terence888 发表于 2024-10-19 15:23:27

pytorch的nn模型训练数据

class DNN(nn.Module):

    def __init__(self):
      super(DNN, self).__init__()
      self.dense_layers = Sequential(
            Linear(7, 256),
            ReLU(),
            Dropout(),
            Linear(256, 32),
            ReLU(),
            Dropout()
      )
      self.output_layer = Sequential(
            Linear(32, 1)
      )

    def forward(self, x):
      x = self.dense_layers(x)
      x = self.output_layer(x)
      return x

上述构造simplenn这个函数的过程中,
为什么要建立构造函数__init__?并在里面建立神经网络层?super(DNN, self).__init__()是什么意思

FishC 发表于 2024-10-19 15:30:19

在PyTorch中,构造函数`__init__`用于初始化类的实例,它在创建对象时会自动调用。为神经网络模型定义`__init__`有几个重要原因:

1. **初始化神经网络层**:在`__init__`函数中,我们定义神经网络的层(如全连接层、激活函数、Dropout层等)。这使得网络的结构在实例化模型时被确定下来,用户可以方便地创建和管理多层模型。

2. **配置层参数**:在`__init__`中,我们可以设置层的参数,比如每一层的输入和输出节点数。这使模型更灵活并易于调整。

3. **继承父类的初始化**:`super(DNN, self).__init__()`调用了父类`nn.Module`的`__init__`方法。`nn.Module`是PyTorch中所有神经网络模块的基类,包含了许多神经网络训练所需的基本功能。通过调用`super()`,我们继承了这些功能,如参数管理、模型保存和加载等。这样,我们的模型`DNN`就可以利用PyTorch提供的所有便利功能。

总结来说,`__init__`用于设置模型的结构,并确保模型具有PyTorch框架的所有基础功能。

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

Terence888 发表于 2024-10-19 15:34:30

FishC 发表于 2024-10-19 15:30
在PyTorch中,构造函数`__init__`用于初始化类的实例,它在创建对象时会自动调用。为神经网络模型定义`__in ...

class SimpleNN(nn.Module):
    def __init__(self):
      super().__init__()
      self.layer1 = nn.Linear(5, 128)
      self.layer2 = nn.Linear(128, 256)
      self.layer3 = nn.Linear(256, 128)
      self.layer4 = nn.Linear(128, 1)

    def forward(self, x):
      x = self.layer1(x)
      x = F.relu(x)
      x = self.layer2(x)
      x = F.relu(x)
      x = self.layer3(x)
      x = F.relu(x)
      x = self.layer4(x)
      x = torch.sigmoid(x)
      return x
和这种定义方式有什么相似之处

FishC 发表于 2024-10-19 15:41:53

Terence888 发表于 2024-10-19 15:34
class SimpleNN(nn.Module):
    def __init__(self) ...

两个模型定义方式的相似之处如下:

1. **都是子类化自 `nn.Module`**:两种方式都使用了PyTorch的`nn.Module`作为基类,表明它们都是神经网络模型。通过继承`nn.Module`,可以充分利用PyTorch提供的神经网络功能。

2. **使用`__init__`方法初始化网络层**:在两个类中,`__init__`方法都被用来初始化网络层。这是定义神经网络结构的标准方式。

3. **使用分层结构**:两种模型都分为多个线性层(`nn.Linear`),并且逐层进行数据传递。在模型构建中,每一层的输出被传递到下一层。

4. **激活函数的应用**:两者都在某些层之间应用了激活函数。`SimpleNN`使用了`F.relu`作为激活函数,而之前的模型使用了`ReLU`对象,不过其核心功能相似,都是对线性层的非线性变换。

5. **前向传递通过`forward`定义**:两者都定义了`forward`方法来描述数据在模型中的流动过程。这是PyTorch中定义数据如何通过模型的标准方法。

6. **输出变换**:在最后输出层,`SimpleNN`使用了`torch.sigmoid`作为非线性变换,而之前的模型没有明确提到输出层的活化函数。

总结来说,这两种方式在结构初始化、激活函数使用和数据前向传递方式上非常相似,都是标准的PyTorch神经网络定义。主要区别在于具体层的数量和参数、激活函数的选择以及对输出层的处理方式。

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

Terence888 发表于 2024-10-19 17:00:15

FishC 发表于 2024-10-19 15:41
两个模型定义方式的相似之处如下:

1. **都是子类化自 `nn.Module`**:两种方式都使用了PyTorch的`n ...

nn_train = data_train.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Sex_.*|Embarked_.*|Pclass_.*')
X = nn_train.drop(columns='Survived')
y = nn_train['Survived']

fold_size = X.shape // 5

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)
k折交叉验证中取出第k次的训练数据和验证数据,代码报错
Cell In, line 8
    for j in range(k):
    ^
IndentationError: unexpected indent

FishC 发表于 2024-10-19 17:00:25

Terence888 发表于 2024-10-19 17:00
nn_train = data_train.filter(regex='Survived|Age_. ...

你的代码中存在一个缩进错误,`for j in range(k):`行前面的缩进不一致导致了这个错误。让我们来修正一下代码,并确保逻辑上是正确的:

nn_train = data_train.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Sex_.*|Embarked_.*|Pclass_.*')
X = nn_train.drop(columns='Survived')
y = nn_train['Survived']# 应该选择'Survived'这一列作为标签

fold_size = len(X) // 5# 使用len(X)来计算数据量

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((X_train, X_part), 0)
      y_train = torch.cat((y_train, y_part), 0)

此代码的几个修正点:
1. **缩进问题**:确保`for`循环的缩进是正确的,从而避免`IndentationError`。
2. **索引和切片**:使用`slice`来正确获取训练集和验证集的切片。
3. **`y`选择错误的更正**:在最初的`y = nn_train`中,应该选择`Survived`列作为目标(标签)。
4. **使用`len(X)`**:计算`fold_size`时使用`len(X)`而不是`X.shape`。
5. **`torch.cat`的参数**:在调用`torch.cat`时,需要传递一个包含张量的元组,如`(X_train, X_part)`。

记得在实际运行时需确保变量`k`和`i`已经定义,且`pandas`和`torch`已经正确导入。这样修改后应该可以正确执行分割数据集的操作。

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

Terence888 发表于 2024-10-19 17:09:32

FishC 发表于 2024-10-19 17:00
你的代码中存在一个缩进错误,`for j in range(k):`行前面的缩进不一致导致了这个错误。让我们来修正一 ...

---------------------------------------------------------------------------
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 10
      8 for j in range(5):
      9         idx = slice(j * fold_size, (j + 1) * fold_size)
---> 10         X_part, y_part = X, y
   11         if j == i:
   12             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-19 17:09:41

Terence888 发表于 2024-10-19 17:09
-------------------------------------------------- ...

根据错误信息,您正在尝试使用不正确的方式索引pandas DataFrame中的数据。在这段代码中,您试图通过`slice`对象对X和y进行索引,而这在pandas中是不直接支持的。您需要通过行索引来选择。

首先,确保X和y都是适当的pandas DataFrame或Series。

以下是如何根据索引正确地进行分割,以避免这种错误:

nn_train = data_train.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Sex_.*|Embarked_.*|Pclass_.*')
X = nn_train.drop(columns='Survived')
y = nn_train['Survived']# 确保y是正确的Series

fold_size = len(X) // 5

X_train, y_train = None, None
k = 5# 确保定义k
i = 0# 确保定义i, 这里假设你想验证第i个分区

for j in range(k):
    start_idx = j * fold_size
    end_idx = (j + 1) * fold_size
    X_part = X.iloc# 使用.iloc根据行索引获取数据
    y_part = y.iloc

    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 = pd.concat(, axis=0)
      y_train = pd.concat(, axis=0)

1. **`iloc`方法**:用于通过整数切片来选择DataFrame的行。这是将索引从错误的多slice转换为适合pandas索引的方法。

2. **`pd.concat`**:用于连接多个DataFrame或Series,`axis=0`表示进行行追加。这代替了`torch.cat`,因为在分割数据阶段,最好使用pandas的工具进行处理。

这段修改后的代码应该可以修复你的错误,并正确地执行数据集的k折分割。

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

Terence888 发表于 2024-10-19 18:41:17

FishC 发表于 2024-10-19 17:09
根据错误信息,您正在尝试使用不正确的方式索引pandas DataFrame中的数据。在这段代码中,您试图通过`s ...

def load_array(data_arrays, batch_size, is_train=True):#@save
    """Construct a PyTorch data iterator."""
    dataset = data.TensorDataset(*data_arrays)
    return data.DataLoader(dataset, batch_size, shuffle=is_train)
```
为什么要进行这步操作?其中data是什么

FishC 发表于 2024-10-19 18:41:24

Terence888 发表于 2024-10-19 18:41
def load_array(data_arrays, batch_size, is_train=T ...

在这个代码片段中,`load_array`函数的目的是将给定的数据数组(`data_arrays`)转换成一个PyTorch的数据迭代器,以便在训练或评估模型时能够批量读取数据。这是为了简化数据处理过程并提高效率的重要步骤。

具体解释如下:

1. **`data.TensorDataset(*data_arrays)`**:
   - `TensorDataset`是PyTorch中的一个类,用于将特征和标签组合到一个数据集(dataset)对象中。在这个例子中,`*data_arrays`代表将传入的多个张量数组(特征和标签)解包成多个独立的参数,以便创建`TensorDataset`。

2. **`data.DataLoader(...)`**:
   - `DataLoader` 是 PyTorch 中用于加载数据的迭代器。它提供了多线程的数据加载、可定制的批次化处理机制(通过`batch_size`控制每次返回的数据量),以及数据的随机打乱(通过`shuffle`参数)。当`is_train`为`True`时,数据将被随机打乱,以增加训练的随机性,从而有助于提高模型的泛化能力。

3. **`data`**:
   - 这通常是指 `torch.utils.data` 模块,该模块包含了创建数据集和数据加载器的重要工具。PyTorch通过这个模块提供了一系列方便的数据处理接口。

综上所述,这个函数有助于在训练过程中以适当的批量读取数据,有效管理和策划数据,以便更好地利用PyTorch的训练功能。如果您使用该函数,请确保导入了正确的模块,如 `from torch.utils import data`。

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

Terence888 发表于 2024-10-19 18:56:16

FishC 发表于 2024-10-19 18:41
在这个代码片段中,`load_array`函数的目的是将给定的数据数组(`data_arrays`)转换成一个PyTorch的数 ...

from torch.utils import data
nn_train = data_train.filter(regex='Survived|Age_.*|SibSp|Parch|Fare_.*|Sex_.*|Embarked_.*|Pclass_.*')
X = nn_train.drop(columns='Survived')
y = nn_train['Survived']
dataset = data.TensorDataset(X, y)
train_iter = data.DataLoader(dataset,batch_size=99)

报错---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In, line 5
      3 X = nn_train.drop(columns='Survived')
      4 y = nn_train['Survived']
----> 5 dataset = data.TensorDataset(X, y)
      6 train_iter = data.DataLoader(dataset,batch_size=99)

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.size(0) == tensor.size(0) for tensor in tensors), "Size mismatch between tensors"
    205   self.tensors = tensors

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

TypeError: 'int' object is not callable

FishC 发表于 2024-10-19 18:56:24

Terence888 发表于 2024-10-19 18:56
from torch.utils import data
nn_train = data_trai ...

您的代码会报`TypeError`,是因为`data.TensorDataset`期望的是PyTorch张量(`torch.Tensor`),而不是pandas的DataFrame对象。因此你需要先将`X`和`y`这些数据转换为PyTorch张量。

以下是如何修正代码:

import torch
from torch.utils import data

# 从DataFrame转换为张量
X = torch.tensor(nn_train.drop(columns='Survived').values, dtype=torch.float32)
y = torch.tensor(nn_train['Survived'].values, dtype=torch.float32)

# 创建TensorDataset
dataset = data.TensorDataset(X, y)

# 创建DataLoader
train_iter = data.DataLoader(dataset, batch_size=99)

### 修正说明
1. **转换为张量**:`torch.tensor()`用于将numpy数组或列表转换为PyTorch张量类型。这里指定了数据类型`dtype=torch.float32`,以确保与PyTorch的计算兼容。通常,特征和标签的类型都是浮点数。
   
2. **选择正确的列作为标签**:之前的`y`直接用到了完整的`nn_train`,应该选出`'Survived'`列作为标签。

以上改动将帮助你成功地创建一个可以用于PyTorch模型训练的数据加载器。

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

Terence888 发表于 2024-10-20 10:04:31

FishC 发表于 2024-10-19 18:56
您的代码会报`TypeError`,是因为`data.TensorDataset`期望的是PyTorch张量(`torch.Tensor`),而不是 ...

data_set = pd.concat((train.drop(['Survived'], axis = 1), test), axis = 0)

data_set = data_set.drop(['PassengerId', 'Name', 'Sex', 'Ticket', 'Cabin', 'Embarked'], axis = 1)
data_set = data_set.fillna(data_set.mean())

n_train = train.shape
train_x, test_x = data_set[:n_train], data_set
train_y = train['Survived']

train_x = train_x.values
test_x = test_x.values
train_y = train_y.values

import torch.optim as optim
from torch.autograd import Variable
from torch.utils.data import DataLoader, SubsetRandomSampler
from sklearn.model_selection import KFold

k_folds = 5
kfold = KFold(n_splits=k_folds, shuffle=True)

simple_dataset = SimpleDataset(train_x, train_y)

loss_list = []
acc_list = []

for fold, (train_ids, valid_ids) in enumerate(kfold.split(simple_dataset)):
    print(f'FOLD {fold}')
    print('--------------------------------')
    train_subsampler = SubsetRandomSampler(train_ids)
    valid_subsampler = SubsetRandomSampler(valid_ids)
   
    train_loader = DataLoader(simple_dataset, batch_size=99, sampler=train_subsampler)
    valid_loader = DataLoader(simple_dataset, batch_size=99, sampler=valid_subsampler)
   
    simple_nn = SimpleNN()
    optimizer = optim.Adam(simple_nn.parameters(), lr=0.01)
    error = nn.BCELoss()
   
    for epoch in range(300):
      with torch.no_grad():
            valid_loss = 0
            num_right = 0
            for tensor_x, tensor_y in valid_loader:
                tensor_x = tensor_x.float()
                tensor_y = tensor_y.float().reshape(-1, 1)
                output = simple_nn(tensor_x)
                loss = error(output, tensor_y)
                valid_loss += loss.item() * len(tensor_x)
                result =
                num_right += np.sum(np.array(result) == tensor_y.numpy().reshape(-1))
            
            valid_loss = valid_loss / len(valid_loader.sampler.indices)
            valid_accuracy = num_right / len(valid_loader.sampler.indices)
      
            if epoch % 50 == 0:
                print('Valid Loss: {} Accuracy: {} Epoch:{}'.format(valid_loss, valid_accuracy, epoch))

      train_loss = 0
      num_right = 0
      for tensor_x, tensor_y in train_loader:
            tensor_x = tensor_x.float()
            tensor_y = tensor_y.float().reshape(-1, 1)
            optimizer.zero_grad()
            output = simple_nn(tensor_x)
            loss = error(output, tensor_y)
            loss.backward()
            optimizer.step()

            train_loss += loss.item() * len(tensor_x)
            result =
            num_right += np.sum(np.array(result) == tensor_y.numpy().reshape(-1))
      
      train_loss = train_loss / len(train_loader.sampler.indices)
      accuracy = num_right / len(train_loader.sampler.indices)
   
      if epoch % 50 == 0:
            print('Loss: {} Accuracy: {} Epoch:{}'.format(train_loss, 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)))
帮我解读一下以上代码

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

FishC 发表于 2024-10-19 18:56
您的代码会报`TypeError`,是因为`data.TensorDataset`期望的是PyTorch张量(`torch.Tensor`),而不是 ...

for fold, (train_ids, valid_ids) in enumerate(kfold.split(simple_dataset)):
    print(f'FOLD {fold}')
    print('--------------------------------')
    train_subsampler = SubsetRandomSampler(train_ids)
    valid_subsampler = SubsetRandomSampler(valid_ids)
   
    train_loader = DataLoader(simple_dataset, batch_size=99, sampler=train_subsampler)
    valid_loader = DataLoader(simple_dataset, batch_size=99, sampler=valid_subsampler)
上述使用k折交叉验证获取数据迭代器,其中
问题一:simple_dataset = SimpleDataset(train_x, train_y)作用是什么?
问题二:SubsetRandomSampler(train_ids)作用是什么
问题三:enumerate(kfold.split(simple_dataset))使用enumerate函数迭代获取的数据是什么样的

FishC 发表于 2024-10-20 10:17:37

Terence888 发表于 2024-10-20 10:11
for fold, (train_ids, valid_ids) in enumerate(kfol ...

好的,我们一起看看这段代码所做的事情。

### 问题一:`simple_dataset = SimpleDataset(train_x, train_y)`作用是什么?

`SimpleDataset`应该是您自定义的一个子类,继承自`torch.utils.data.Dataset`。其作用是将`train_x`和`train_y`整合成一个可以被PyTorch的数据加载器(`DataLoader`)使用的数据集对象。它的典型实现会重载两个方法:`__len__()`返回数据集中样本的数量,`__getitem__()`返回指定索引(`idx`)的特征和标签。一旦这个`Dataset`对象创建好,它就可以分配数据给不同的数据加载器。

### 问题二:`SubsetRandomSampler(train_ids)`作用是什么?

`SubsetRandomSampler`是PyTorch的一个采样器类。给定一组索引(如`train_ids`),它会在这些索引中随机采样。这样做可以创建出一个子样本集。在上面的代码中,`train_ids`代表用于训练的样本索引。通过提供这些索引给`SubsetRandomSampler`,你可以确保从数据集中随机选择这些样本。这在划分训练和验证集时非常有用。

### 问题三:`enumerate(kfold.split(simple_dataset))`使用`enumerate`函数迭代获取的数据是什么样的?

`enumerate`是一个内置Python函数,它在迭代时同时提供元素的索引和元素本身。在这个上下文中,`kfold.split(simple_dataset)`会返回一个生成器,该生成器每次迭代产生一个由训练样本索引和验证样本索引组成的元组,格式为:`(train_indices, test_indices)`。

`enumerate(kfold.split(simple_dataset))`会为每个这样的元组提供一个索引`fold`。因此,`fold`是该交叉验证折的编号,`train_ids`和`valid_ids`是该折对应的训练集和验证集样本索引。

总结:
- `simple_dataset`将特征和标签组织成数据集对象,便于使用。
- `SubsetRandomSampler`用于从指定索引中随机采样数据。
- `enumerate(kfold.split(simple_dataset))`有助于遍历交叉验证的每个折次,并索引每次划分。

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

Terence888 发表于 2024-10-20 10:32:49

FishC 发表于 2024-10-20 10:17
好的,我们一起看看这段代码所做的事情。

### 问题一:`simple_dataset = SimpleDataset(train_x, t ...

train_loss += loss.item() * len(tensor_x)
这段代码怎么理解

FishC 发表于 2024-10-20 10:45:37

Terence888 发表于 2024-10-20 10:32
train_loss += loss.item() * len(tensor_x)
这段代 ...

这段代码中的 `train_loss += loss.item() * len(tensor_x)` 主要负责累积当前批次的损失,具体解释如下:

1. **`loss`**:`loss` 是计算得出的当前批次的损失值,这通常是一个 PyTorch 的张量。

2. **`loss.item()`**:`loss` 是一个张量时,如果您想要得到其数值表示,可以使用 `.item()` 方法将单一值张量转换为 Python 的数值类型(比如浮点数)。这是因为通常张量是多维的,但通过损失函数计算后往往产生的是一个标量张量。

3. **`len(tensor_x)`**:`tensor_x` 是当前批次中的一组训练样本,`len(tensor_x)` 返回的是这个批次中样本的数目,等同于 `batch_size`,除非最后一个批次可能样本数不足。

4. **`train_loss += loss.item() * len(tensor_x)`**:这里的目的是,根据当前批次的损失和批次的规模累计损失。一般情况下 `loss.item()` 已经是批均损失。如果需要积累总的损失,乘以样本数量后累计到 `train_loss` 中。这使得后续计算总损失或平均损失时可以获得更多的自由和准确性。

总结:该行代码通过累积每个批次的损失乘以批次大小,最终得到整个数据集上的总训练损失,为后续可能的损失输出、损失绘图或其它分析提供基础数量支持。

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

Terence888 发表于 2024-10-20 10:53:12

FishC 发表于 2024-10-20 10:45
这段代码中的 `train_loss += loss.item() * len(tensor_x)` 主要负责累积当前批次的损失,具体解释如 ...

num_right += np.sum(np.array(result) == tensor_y.numpy().reshape(-1))
这段代码如何解读

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

Terence888 发表于 2024-10-20 10:53
num_right += np.sum(np.array(result) == tensor_y.n ...

这段代码的目的是计算当前批次中模型预测正确的样本数量。以下是对这段代码的详细解读:

1. **`result`**:假设这是模型的预测结果,通常是一个张量或数组,包含了对每个样本的预测值。

2. **`tensor_y`**:这是当前批次的真实标签,通常是一个PyTorch张量。

3. **`tensor_y.numpy().reshape(-1)`**:将`tensor_y`从PyTorch张量转换为NumPy数组,并将其展平为一维数组。`reshape(-1)`的作用是将多维数组展平为一维,这样可以方便地与`result`进行逐元素比较。

4. **`np.array(result)`**:将`result`转换为NumPy数组,以便与`tensor_y`的NumPy数组进行比较。

5. **`np.array(result) == tensor_y.numpy().reshape(-1)`**:逐元素比较预测结果和真实标签,生成一个布尔数组,其中每个元素表示对应位置的预测是否正确(`True`表示正确,`False`表示错误)。

6. **`np.sum(...)`**:对布尔数组进行求和,`True`被视为1,`False`被视为0,因此求和结果即为预测正确的样本数量。

7. **`num_right += ...`**:将当前批次中预测正确的样本数量累加到`num_right`中,`num_right`用于记录到目前为止所有批次中预测正确的总样本数。

总结:这段代码通过比较预测结果和真实标签,计算出当前批次中预测正确的样本数量,并将其累加到总计数中。

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

Terence888 发表于 2024-10-20 11:13:23

FishC 发表于 2024-10-20 10:53
这段代码的目的是计算当前批次中模型预测正确的样本数量。以下是对这段代码的详细解读:

1. **`resu ...

with torch.no_grad():
            valid_loss = 0
            num_right = 0
            for tensor_x, tensor_y in valid_loader:
                tensor_x = tensor_x.float()
                tensor_y = tensor_y.float().reshape(-1, 1)
                output = simple_nn(tensor_x)
                loss = error(output, tensor_y)
                valid_loss += loss.item() * len(tensor_x)
                result =
                num_right += np.sum(np.array(result) == tensor_y.numpy().reshape(-1))
            
            valid_loss = valid_loss / len(valid_loader.sampler.indices)
            valid_accuracy = num_right / len(valid_loader.sampler.indices)
      
            if epoch % 50 == 0:
                print('Valid Loss: {} Accuracy: {} Epoch:{}'.format(valid_loss, valid_accuracy, epoch))

为什么验证集不执行梯度下降
页: [1] 2
查看完整版本: pytorch的nn模型训练数据