在 dask 中洗牌数据
Posted
技术标签:
【中文标题】在 dask 中洗牌数据【英文标题】:Shuffling data in dask 【发布时间】:2018-04-01 05:09:58 【问题描述】:这是Subsetting Dask DataFrames 的后续问题。我希望在将数据批量发送到 ML 算法之前,对 dask 数据帧 中的数据进行洗牌。
该问题的答案是执行以下操作:
for part in df.repartition(npartitions=100).to_delayed():
batch = part.compute()
但是,即使我要洗牌批次的内容,我也有点担心它可能不理想。数据是一个时间序列集,因此每个分区内的数据点高度相关。
我最理想的情况是:
rand_idx = np.random.choice(len(df), batch_size, replace=False)
batch = df.iloc[rand_idx, :]
这适用于 pandas 但不适用于 dask。有什么想法吗?
编辑 1:潜在解决方案
我试过了
train_len = int(len_df*0.8)
idx = np.random.permutation(len_df)
train_idx = idx[:train_len]
test_idx = idx[train_len:]
train_df = df.loc[train_idx]
test_df = df.loc[test_idx]
但是,如果我尝试执行 train_df.loc[:5,:].compute()
这将返回 124451 行数据框。很明显使用 dask 是错误的。
【问题讨论】:
【参考方案1】:对于这里的人们真的只是想像标题所暗示的那样洗牌: 这很昂贵
import numpy as np
random_idx = np.random.permutation(len(sd.index))
sd.assign(random_idx=random_idx)
sd = sd.set_index('x', sorted=True)
【讨论】:
【参考方案2】:我最近遇到了同样的问题,并想出了一个不同的方法,使用这个 pull request 中介绍的 dask 数组和 shuffle_slice
它对整个样本进行洗牌
import numpy as np
from dask.array.slicing import shuffle_slice
d_arr = df.to_dask_array(True)
df_len = len(df)
np.random.seed(42)
index = np.random.choice(df_len, df_len, replace=False)
d_arr = shuffle_slice(d_arr, index)
并转换回 dask 数据帧
df = d_arr.to_dask_dataframe(df.columns)
对我来说,它适用于大型数据集
【讨论】:
【参考方案3】:如果您想将数据框分成训练和测试子集,sklearn.model_selection.train_test_split
就是这样做的,它适用于 pandas.DataFrame
。 (以there 为例)
对于您将它与dask
一起使用的情况,您可能会对库dklearn
感兴趣,它似乎实现了此功能。
为此,我们可以使用 train_test_split 函数,它反映 scikit-learn 同名函数。我们将保留 20% 的 行:
from dklearn.cross_validation import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y,test_size=0.2)
更多信息here。
注意:我没有对dklearn
进行任何测试,这只是我遇到的一个问题,但我希望它可以帮助。
编辑:dask.DataFrame.random_split
呢?
例子
50/50 分割
>>> a, b = df.random_split([0.5, 0.5])
80/10/10 分裂,随机状态一致
>>> a, b, c = df.random_split([0.8, 0.1, 0.1], random_state=123)
说明了用于 ML 应用程序here
【讨论】:
嗨 Fabien,恐怕 dklearn 已经不存在了。我实际上看到了那篇博文,但由于这个原因,我无法从中得到太多。 @Sachin_ruk ,我想我找到了另一个解决方案(内置于dask.DataFrame
),请参阅我的编辑。【参考方案4】:
我建议在您的数据框中添加一列随机数据,然后使用它来设置索引:
df = df.map_partitions(add_random_column_to_pandas_dataframe, ...)
df = df.set_index('name-of-random-column')
【讨论】:
第一行我不能简单地完成df['rand_index'] = np.random.permutation(len(df))
吗?
似乎应该内置这种行为。所以我们可以自动添加一个未使用的随机列,然后对整个数据帧进行洗牌。打乱每个单独的分区是不够的,必须打乱整个数据帧。
本方案相关:***.com/questions/46923274/…以上是关于在 dask 中洗牌数据的主要内容,如果未能解决你的问题,请参考以下文章