はじめに
パソコンのメモリに載せないほどの容量が大きいデータセットがあるとしましょう。パソコンのメモリが16GBに対し、データセットの容量が200GBのことを言っています。この時には、データセットがメモリに乗らないため、データを逐次に取り出し、平均と分散(共分散)を計算・更新する方法をよくとります。今日はその方法をご説明します。
巨大データセットの生成
Featureが六つ、データの数が2000000の仮想のデータセットを作成し、csvファイルに保存します。csvファイルの容量は約2GBになります。
- 〇を二つ追記すれば、200GBのCSVファイル作成も可能です。パソコンの処理がかなり重くなります。
import numpy as np
import pandas as pd
# create a pandas DataFrame with random data
num_data = 20000000
df = pd.DataFrame(np.random.rand(num_data, 6),
columns=['feature1', 'feature2', 'feature3', 'feature4', 'feature5', 'feature6'])
df.to_csv('./datasets/large_dataset.csv', index=False)
一般的な平均・共分散の計算
メモリにデータセットを乗せ、一気に平均・共分散を計算します。大体、この段階でパソコンのメモリ利用率が100%になり、動作が重くなります。(Freezeされ、計算が終わらないこともあります。)
import numpy as np
import pandas as pd
df = pd.read_csv('./datasets/large_dataset.csv')
# calculate the average of each feature using numpy
averages_numpy = np.mean(df, axis=0)
print("Averages:\n", averages_numpy)
# calculate the covariance matrix using numpy
covariance_numpy = np.cov(df, rowvar=False)
print("Covariance:\n", covariance_numpy)
逐次方法の平均・共分散の計算
一気にデータを取り出すのではなく、chunk単位で取り出します。
その都度、データの統計量を計算し、新しいchunkが追加されるときにそれを更新する方法です。
考えてみれば、Deep Learningの学習ってこのようなやり方でやっていますね。
コードを書いてみます。 前章で作成したデータセットを利用します。
import numpy as np
import pandas as pd
#data file name
fName = './datasets/large_dataset.csv'
#データセットの次元確認のため、
df_sample = pd.read_csv(fName, chunksize=5).get_chunk()
# http://blog.livedoor.jp/itengineerblog/archives/15060246.html
print(df_sample.head())
print(df_sample.shape)
num_feature = df_sample.shape[1]
print(df_sample.values) #data values
# define the chunk size
chunk_size = 10000
# initialize the counters
count = 0
sums = np.zeros(num_feature) #number of features
sums_sq = np.zeros((num_feature, num_feature)) #(n features, n features)
#extract chunk
for i, chunk in enumerate(pd.read_csv(fName, chunksize=chunk_size)):
data = chunk.values
n = data.shape[0]
count += n
sums += np.sum(data, axis=0)
sums_sq += np.dot(data.T, data)
# calculate the mean and covariance
mean = sums / count
cov = (sums_sq / count) - np.outer(mean, mean)
print("Mean:\n", mean)
print("Covariance:\n", cov)
コードを説明しますと、chunk単位を決めます。こちらでは、chunk_size = 10000になっていて、データを10000個単位で取り出します。
pd.read_csv(fName, chunksize=chunk_size) read_csv()のオプションにchunksizeがあります。これを使うと、繰り返しながらchunk_sizeでデータと取り出してくれます。
計算結果
Mean:
[0.50001305 0.49991214 0.5000087 0.50006749 0.49998438 0.49998971]
Covariance:
[[ 8.33555032e-02 2.20143863e-05 3.08444789e-05 -1.33690942e-05
3.14321419e-05 4.73431331e-06]
[ 2.20143863e-05 8.33174013e-02 -1.83491930e-05 4.04559066e-05
3.32762766e-05 1.42837743e-05]
[ 3.08444789e-05 -1.83491930e-05 8.33674115e-02 4.37566769e-05
-1.07664114e-05 -5.27177048e-07]
[-1.33690942e-05 4.04559066e-05 4.37566769e-05 8.33394753e-02
-1.39420447e-05 1.99202341e-05]
[ 3.14321419e-05 3.32762766e-05 -1.07664114e-05 -1.39420447e-05
8.33050283e-02 -1.85984257e-06]
[ 4.73431331e-06 1.42837743e-05 -5.27177048e-07 1.99202341e-05
-1.85984257e-06 8.33443293e-02]]
まとめ
多次元データの平均・共分散の逐次計算について、ご説明いたしました。
参考資料