Sklearn中T-SNE报含NaN或Inf数据错误的排查求助
解决TSNE报错"array must not contain infs or NaNs"的问题
这种情况确实很让人头疼——明明已经确认过数据里没有NaN和Inf,结果TSNE还是抛出了这个错误。结合你的代码和场景,我来分析下可能的原因和对应的解决办法:
可能的诱因
- 浮点数精度的隐性问题:你用
np.isnan检查了NaN,但没排查Inf;或者存在一些接近浮点数溢出边界的极小/极大值,在TSNE内部的计算(比如距离计算、梯度更新)中被转化成了Inf/NaN。TruncatedSVD输出的float类型数据,可能存在这类精度隐患。 - 数据尺度不匹配:TSNE对数据的尺度非常敏感,SVD降维后的特征数值范围可能波动很大,没有做标准化的话,容易触发计算中的数值异常。
- 旧版本库的bug:你用的是Python3.5和较老的sklearn/scipy版本,这些版本的TSNE模块可能存在已知的数值稳定性问题,在特定数据分布下会出现中间计算溢出。
具体解决方法
1. 先对SVD降维后的数据做标准化/归一化
这是最常见也最有效的解决手段,把数据缩放到合适的尺度后,TSNE的计算会更稳定:
from sklearn.preprocessing import StandardScaler # 标准化数据,让每个特征均值为0,方差为1 scaler = StandardScaler() svd_scaled = scaler.fit_transform(svd_reduced_data) # 再传入TSNE处理 tsne = TSNE(n_components=2, n_iter=300, random_state=42) tsne_result = tsne.fit_transform(svd_scaled)
如果标准化效果不好,也可以试试MinMaxScaler把数据缩放到[0,1]区间:
from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() svd_scaled = scaler.fit_transform(svd_reduced_data)
2. 排查并处理极端值
先看看数据里有没有接近浮点数边界的数值:
print("数据最小值:", svd_reduced_data.min()) print("数据最大值:", svd_reduced_data.max())
如果存在极大/极小值,用np.clip做截断处理:
# 把数值限制在[-1e10, 1e10]范围内,避免溢出 svd_clipped = np.clip(svd_reduced_data, -1e10, 1e10)
3. 升级相关库版本(如果环境允许)
Python3.5已经停止维护了,对应的sklearn/scipy版本也比较旧,升级到较新的版本(比如sklearn 0.24+)可以修复很多数值计算上的bug。如果你的项目可以兼容,这是从根源解决问题的办法。
4. 调整TSNE的参数
尝试调整perplexity(默认30)或者增加n_iter的次数,有时候参数不合适也会引发计算异常:
# 调整perplexity并增加迭代次数 tsne = TSNE(n_components=2, n_iter=1000, perplexity=50, random_state=42) tsne_result = tsne.fit_transform(svd_reduced_data)
验证步骤
处理完数据后,记得再检查一遍:
print("NaN数量:", np.isnan(svd_scaled).sum()) print("Inf数量:", np.isinf(svd_scaled).sum())
内容的提问来源于stack exchange,提问作者Baktaawar
相关产品推荐
相关产品推荐

