You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch中numpy.ndarray转Tensor失败及AttributeError问题求助

问题

  • 环境:numpy 1.25.1、Python 3.10、Torch 2.0.1
  • 场景:自定义EmbeddingDataset类并设置了transform和target_transform,实例化test_data时指定transform=ToTensor(),但直接获取test_data.X得到的仍是numpy.ndarray类型
  • 报错情况:
    1. 调用X_test.matmul(w)触发:AttributeError: 'numpy.ndarray' object has no attribute 'matmul'
    2. 尝试X_test.torch.tensor(X).float()触发:AttributeError: 'numpy.ndarray' object has no attribute 'torch'
  • 疑问:
    1. 为何X_test没有被转换为Tensor?
    2. 如何修复这些属性错误?

相关代码:

import numpy as np
import torch
import pickle
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torchvision.transforms import ToTensor, Lambda

# 自定义Dataset类
class EmbeddingDataset(Dataset):
    def __init__(self, embedding_fp, transform=None, target_transform=None):
        with open(embedding_fp, "rb") as fIn:
            stored_data = pickle.load(fIn)
            stored_labels = stored_data['labels']
            stored_embeddings = stored_data['embeddings']
        self.X = stored_embeddings 
        self.y = stored_labels.to_numpy()
        
        self.transform = transform
        self.target_transform = target_transform

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

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

        if self.transform:
            X = self.transform(X)
        if self.target_transform:
            y = self.target_transform(y)
        return X, y
        
# 实例化数据集
train_data = EmbeddingDataset('embeddings_db_train.pkl', 
                              transform=ToTensor(),
                              target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1)))
X_train = train_data.X
y_train = train_data.y

test_data = EmbeddingDataset('embeddings_db_test.pkl', 
                             transform=ToTensor(),
                             target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1)))
X_test = test_data.X
y_test = test_data.y

print(type(X_test))  # 输出:numpy.ndarray

# 相关函数定义
def plain_accuracy(self, X_test, y_test):
    # 在原始数据集上评估模型准确率
    w = torch.tensor(self.weight)
    b = torch.tensor(self.bias)
    out = torch.softmax(X_test.matmul(w) + b).reshape(-1, 1)
    correct = torch.abs(y_test - out) < 0.5
    return correct.float().mean() 

def softmax(self, enc_x):
    val_out = enc_x.T.dot(self.weight) + self.bias
    val_expo = np.array([EncryptedLR.our_exp(x) for x in val_out])
    val_pred = np.array([x * EncryptedLR.goldschmidt(x, M=1/EncryptedLR.GOLDSCHMIDT_CONST, n=EncryptedLR.GOLDSCHMIDT_ITER) for x in val_expo])
    return val_pred

解答

1. 为何X_test没有被转换为Tensor?

自定义Dataset类中的transform逻辑仅在__getitem__方法中生效——只有当你通过索引(如test_data[0])获取单个样本,或者使用DataLoader批量加载数据时,才会触发transform对数据进行转换。而直接访问test_data.X是读取初始化阶段保存的原始numpy数组,完全没经过transform处理,所以仍是numpy.ndarray类型。

2. 如何修复这些属性错误?

方式一:正确获取经过transform的Tensor数据

如果需要批量的转换后数据,有两种常用方法:

  • 方法1:用DataLoader加载
test_loader = DataLoader(test_data, batch_size=len(test_data), shuffle=False)
X_test_tensor, y_test_tensor = next(iter(test_loader))
  • 方法2:手动遍历Dataset收集
X_test_tensor = []
y_test_tensor = []
for x, y in test_data:
    X_test_tensor.append(x)
    y_test_tensor.append(y)
X_test_tensor = torch.stack(X_test_tensor)
y_test_tensor = torch.stack(y_test_tensor)

方式二:直接转换原始numpy数组

如果不想通过Dataset的__getitem__,可以直接将原始numpy数组转为Tensor:

# 替换原来的X_test = test_data.X
X_test_tensor = torch.tensor(test_data.X).float()
# 或者复用你设置的ToTensor()转换
X_test_tensor = ToTensor()(test_data.X)

修复具体报错的代码

  • 针对matmul错误:numpy数组没有.matmul()方法,要么用np.matmul(X_test, w)或X_test @ w;如果是Tensor则可以用.matmul()或@。
  • 针对错误的Tensor转换:X_test.torch.tensor(X).float()是语法错误,torch是顶级模块,正确写法是torch.tensor(X_test).float()。

修改后的plain_accuracy函数示例:

def plain_accuracy(self, X_test, y_test):
    w = torch.tensor(self.weight)
    b = torch.tensor(self.bias)
    # 先将X_test转为Tensor(如果传入的还是numpy数组)
    if isinstance(X_test, np.ndarray):
        X_test = torch.tensor(X_test).float()
    # 使用Tensor的matmul或@运算符,注意softmax要指定维度
    out = torch.softmax(X_test.matmul(w) + b, dim=1).reshape(-1, 1)
    # 同时确保y_test也是Tensor类型
    if isinstance(y_test, np.ndarray):
        y_test = torch.tensor(y_test).float()
    correct = torch.abs(y_test - out) < 0.5
    return correct.float().mean()

内容的提问来源于stack exchange,提问作者Bluetail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 20:15:40