LoginSignup
0
2

More than 1 year has passed since last update.

データの平均・共分散の逐次計算

Last updated at Posted at 2023-02-18

はじめに

パソコンのメモリに載せないほどの容量が大きいデータセットがあるとしましょう。パソコンのメモリが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]]

まとめ

多次元データの平均・共分散の逐次計算について、ご説明いたしました。

参考資料

0
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2