我有一个相当大的数据集需要进行分解,但它太大无法一次性加载到内存中。经过研究,我发现sklearn的IncrementalPCA是一个不错的选择,但我无法完全弄明白如何使其工作。
我可以正常加载数据:
f = h5py.File('my_big_data.h5')features = f['data']
从这个例子来看,我需要决定从中读取的数据块大小:
num_rows = data.shape[0] # 数据总行数chunk_size = 10 # 每次喂给ipca的行数
然后我可以创建我的IncrementalPCA,逐块流式传输数据,并进行部分拟合(同样来自上面的例子):
ipca = IncrementalPCA(n_components=2)for i in range(0, num_rows//chunk_size): ipca.partial_fit(features[i*chunk_size : (i+1)*chunk_size])
以上操作都没有出错,但我不确定接下来该怎么做。我如何实际进行降维并得到一个新的numpy数组,以便进一步操作和保存?
编辑
上述代码是用于测试我的数据的一个较小子集 – 正如@正确指出的,在最终代码中使用更大的维度数和块大小会更好。
回答:
正如您猜测的那样,拟合过程是正确的,尽管我建议将chunk_size
增加到100或1000(甚至更高,这取决于您数据的形状)。
现在您需要做的就是转换它:
out = my_new_features_dataset # 形状为N x 2for i in range(0, num_rows//chunk_size): out[i*chunk_size:(i+1) * chunk_size] = ipca.transform(features[i*chunk_size : (i+1)*chunk_size])
这应该会给您新的转换后的特征。如果您仍然有太多样本无法装入内存,我建议将out
作为另一个hdf5数据集使用。
此外,我认为将一个庞大的数据集降维到2个组件可能不是一个好主意。但没有了解您的features
的形状就很难说。我建议将其降维到sqrt(features.shape[1])
,这是一个不错的启发式方法,或者专业提示:使用ipca.explained_variance_ratio_
来确定最佳的特征数量,以达到您可接受的信息损失阈值。
编辑:关于explained_variance_ratio_
,它返回一个维度为n_components
的向量(您传递给IPCA的n_components
参数),其中每个值i指示原始数据的方差中有多少百分比由第i个新组件解释。
您可以按照这个答案中的程序来提取前n个组件保留了多少信息:
>>> print(ipca.explained_variance_ratio_.cumsum())[ 0.32047581 0.59549787 0.80178824 0.932976 1. ]
注意:数字是假设您已将IPCA降维到5个组件,从上面的答案中取的虚构数字。第i个数字表示前[0, i]个组件解释了多少原始数据,因为这是解释方差比的累积和。
因此,通常的做法是将您的PCA拟合到与原始数据相同数量的组件上:
ipca = IncrementalPCA(n_components=features.shape[1])
然后,在对整个数据进行训练(通过迭代 + partial_fit
)后,您可以绘制explaine_variance_ratio_.cumsum()
并选择您希望损失多少数据。或者自动完成:
k = np.argmax(ipca.explained_variance_ratio_.cumsum() > 0.9)
上述代码将返回累积数组中第一个值大于0.9
的索引,即指示保留至少90%原始数据的PCA组件数量。
然后您可以调整转换以反映这一点:
cs = chunk_sizeout = my_new_features_dataset # 形状为N x kfor i in range(0, num_rows//chunk_size): out[i*cs:(i+1)*cs] = ipca.transform(features[i*cs:(i+1)*cs])[:, :k]
注意对:k
的切片,只选择前k
个组件而忽略其余部分。