训练真假数据分类模型遇ValueError:输入含无穷大或超float16范围
问题描述
我正在训练一个区分真实与伪造数据的模型,目前因为不清楚如何用单个模型同时训练两个数据集,所以分别为真实数据和伪造数据训练模型。但训练伪造数据模型时触发如下报错:
ValueError: Input X contains infinity or a value too large for dtype('float16')
对应的训练代码如下:
import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score from sklearn.utils import shuffle from sklearn.preprocessing import MinMaxScaler from sklearn.preprocessing import RobustScaler from sklearn.metrics import classification_report from sklearn.metrics import confusion_matrix scaler = RobustScaler() X = np.load("fake_x.npy") x_data_flat = X.reshape(X.shape[0], -1) x_data_scaled = scaler.fit_transform(x_data_flat) y = np.load("fake_y.npy") x_data_flat, y = shuffle(x_data_flat, y) X_train,X_test,y_train,y_test = train_test_split(x_data_scaled,y,test_size=0.1, train_size=0.1) clf = RandomForestClassifier() clf.fit(X_train, y_train) y_pred = clf.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print("Accuracy:", accuracy) print("Classification Report:") print(classification_report(y_test, y_pred)) conf_matrix = confusion_matrix(y_test, y_pred) print("Confusion Matrix:") print(conf_matrix)
数据说明:
- 数据是从real.npz和fake.npz提取的2D谱图,分别保存为real_x.npy、real_y.npy和fake_x.npy、fake_y.npy
- 伪造数据中,X的形状为(750,1998,101),y的形状为(750,496)
- 分类计划通过输入的相似度得分判断所属类别
解决方案
一、解决输入数据的无穷大/数值溢出问题
报错核心是数据中存在无穷大值或数值超出float16范围,按以下步骤处理:
- 检测并清理异常值
在数据缩放前,先处理无穷大、NaN和极端值:
X = np.load("fake_x.npy") x_data_flat = X.reshape(X.shape[0], -1) # 替换无穷大值为NaN,用中位数填充(鲁棒性更强) x_data_flat = np.where(np.isinf(x_data_flat), np.nan, x_data_flat) median_val = np.nanmedian(x_data_flat, axis=0) for col in range(x_data_flat.shape[1]): x_data_flat[:, col] = np.where(np.isnan(x_data_flat[:, col]), median_val[col], x_data_flat[:, col]) # 截断极端值到上下1%分位数范围,避免缩放时溢出 q1 = np.quantile(x_data_flat, 0.01, axis=0) q99 = np.quantile(x_data_flat, 0.99, axis=0) x_data_flat = np.clip(x_data_flat, q1, q99)
- 修正代码逻辑错误
你的代码存在数据-标签不匹配的问题:先缩放得到x_data_scaled,但打乱的是未缩放的x_data_flat,后续划分用了缩放后的特征。正确流程如下:
# 正确顺序:加载数据→扁平化→清理异常→打乱→划分→训练集拟合scaler(避免数据泄露) X = np.load("fake_x.npy") x_data_flat = X.reshape(X.shape[0], -1) y = np.load("fake_y.npy") # 先打乱数据,保证特征和标签对应 x_data_flat, y = shuffle(x_data_flat, y) # 划分训练测试集 X_train,X_test,y_train,y_test = train_test_split(x_data_flat,y,test_size=0.1, train_size=0.1) # 仅用训练集拟合scaler,再转换测试集 scaler = RobustScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # 用缩放后的训练集训练模型 clf = RandomForestClassifier() clf.fit(X_train_scaled, y_train)
- 升级数据类型避免溢出
如果数据默认是float16,先转换为float32/float64再处理:
x_data_flat = x_data_flat.astype(np.float32)
二、用单个模型同时训练真实与伪造数据
不需要分开训练两个模型,合并数据集构建二分类标签即可:
- 合并数据集并生成分类标签
# 加载并扁平化真实数据 real_x = np.load("real_x.npy").reshape(real_x.shape[0], -1) # 加载并扁平化伪造数据 fake_x = np.load("fake_x.npy").reshape(fake_x.shape[0], -1) # 合并所有特征 X_combined = np.vstack([real_x, fake_x]) # 构建二分类标签:真实数据标记为0,伪造数据标记为1 y_combined = np.hstack([np.zeros(real_x.shape[0]), np.ones(fake_x.shape[0])]) # 打乱合并后的数据,保证分布均匀 X_combined, y_combined = shuffle(X_combined, y_combined)
训练单分类模型
后续流程和之前一致:清理异常值→划分数据集→缩放→训练模型。模型直接输出输入数据属于真实/伪造的分类结果。相似度得分的应用
如果需要用相似度得分判断,可让模型输出概率(如clf.predict_proba(X_test)[:,1]得到伪造数据的概率),再设置阈值划分类别;也可以先计算输入与真实/伪造样本的相似度,将相似度作为特征输入分类模型。
内容的提问来源于stack exchange,提问作者KratosGow
相关产品推荐
相关产品推荐

