Numpyのすすめ

schedule 2018/09/29  refresh 2023/11/08

 

 

numpyとは

Pythonは基本的にループ内を毎回コンパイルして実行するのでデータをループして処理するのは時間がかかるので避けねばなりません。

 

そんなわけでPythonの機械学習モジュールのほとんどNumpyという配列全体への操作を1オペレーションで行える多次元配列拡張モジュールを使ってます。

 

以下弊社でよく使っている言語で何パターンか配列の処理速度を測ってみました。

 

 

計測環境

測り方は1.2以降は1.1と同じように測りました。
データ数がすくないので5回の平均をとってます。

 

実行環境

php 5.4.16 (OutofMemoryになったのでphp.iniでmemory_limitを512Mに変更)

perl 5.16.3

python 2.7.5

 

データ数

配列の要素数は100万くらい(もっと多いほうがいいデータがとれますがうちの検証環境がしょぼいのでこのくらいに)

 

リスト

全要素1の初期化

perl forループで代入

 

 

my ($e, $m) = gettimeofday();
my $start = $e + $m / 1000000;
for (my $i = 0; $i < 1000000; $i++) {
$ary[$i] = 1;
}
($e, $m) = gettimeofday();
print($e + $m / 1000000 - $start);

0.130244

 

php forループで代入

 

$ary = array();
$start = microtime(true);
for ($i = 0; $i < 1000000; $i++) {
$ary[$i] = 1;
}
print_r(microtime(true) - $start);

0.221422

 

python forループで代入

 

s = datetime.datetime.today()
start = float(s.minute) * 60 + float(s.second) + float(s.microsecond) / 1000000
ary = []
for i in range(1000000):
ary.append(i)
e = datetime.datetime.today()
print(float(e.minute) * 60 + float(e.second) + float(e.microsecond) / 1000000 - start)


0.161213

 

 

 

python numpyをforループで代入

 

s = datetime.datetime.today()
start = float(s.minute) * 60 + float(s.second) + float(s.microsecond) / 1000000
ary = numpy.array([])
for i in range(1000000):
ary = numpy.append(i)
e = datetime.datetime.today()
print(float(e.minute) * 60 + float(e.second) + float(e.microsecond) / 1000000 - start)

 

 

10分待って終わらないので中断

 

python numpyのonesで初期化

 

s = datetime.datetime.today()
start = float(s.minute) * 60 + float(s.second) + float(s.microsecond) / 1000000
ary = numpy.ones((1000000))
e = datetime.datetime.today()
print(float(e.minute) * 60 + float(e.second) + float(e.microsecond) / 1000000 - start)


0.002626

 

 

 

全要素合計

perl forループで順次加算

 

my $num = 0;
for (my $i = 0; $i < 1000000; $i++) {
$num += $ary[$i];
}

0.093396

 

 

perl foreachループで順次加算

 

my $num = 0;
foreach my $i (@ary) {
$num += $ary[$i];
}

0.078159

 

 

php forループで順次加算

for ($i = 0; $i < 1000000; $i++) {

 $num += $ary[$i];

}

 

0.065996

 

php foreachループで順次加算

 

foreach ($ary as $val) {

 $num += $val;

}

 

0.052462

 

 

python forループで順次加算

for i v in range(len(ary)):

 num += i

 

0.122088

 

python numpyをforループで順次加算

for i v in range(len(ary)):

 num += i

 

0.14291

 

python numpyをsumを使って計算

num = np.sum(ary)

 

0.001414

 

多次元配列

100000*4*4の配列の測定

 

全要素1の初期化

perl forループで代入

my @ary = ();

for (my $i = 0; $i < 100000; $i++) {

 $ary[$i] = ();

  for (my $j = 0; $j < 4; $j++) {

   $ary[$i][$j] = ();

  for (my $k = 0; $k < 4; $k++) {

   $ary[$i][$j][$k] = 1;

  }

 }

}

 

0.587198

 

php forループで代入

$ary = array();

for ($i = 0; $i < 100000; $i++) {

 $ary[$i] = array();

 for ($j = 0; $j < 4; $j++) {

  $ary[$i][$j] = array();

  for ($k = 0; $k < 4; $k++) {

   $ary[$i][$j][$k] = 1;

  }

 }

}

 

0.676906

 

python 配列の中のforループで代入

ary = [[[1] * 4 for i in range(4)] for j in range(100000)]

 

0.446916

 

python numpyをonesで初期化

ary = numpy.ones((10000,4,4))

 

0.000753

 

全要素合計

perl forループで順次加算

my $num = 0;

for (my $i = 0; $i < 100000; $i++) {

 for (my $j = 0; $j < 4; $j++) {

  for (my $k = 0; $k < 4; $k++) {

   $num += $ary[$i][$j][$k];

  }

 }

}

 

0.363232

 

perl foreachループで順次加算

my $num = 0;

foreach my $i (@ary) {

foreach my $j (@$i) {

foreach my $k (@$j) {

$num += $k;

}

}

}

 

0.244424

 

php forループで順次加算

$num = 0;

for ($i = 0; $i < 100000; $i++) {

for ($j = 0; $j < 4; $j++) {

for ($k = 0; $k < 4; $k++) {

$num += $ary[$i][$j][$k];

}

}

}

 

0.303648

 

php foreachループで順次加算

$num = 0;

foreach ($ary as $v1) {

foreach ($v1 as $v2) {

foreach ($v2 as $val) {

$num += $val;

}

}

}

 

0.401962

 

python forループで順次加算

num = 0

for i, v in enumerate(ary):

for j, v2 in enumerate(v):

for k, v3 in enumerate(v2):

num += v3

 

0.454874

 

python numpyをsumで計算

num = np.sum(ary)

 

0.0003

 

結果まとめ

 

言語 リスト 多次元配列
初期化 計算 初期化 計算
perl for 0.130244 0.093396 0.587198 0.363232
perl foreach - 0.078159 - 0.244424
php for 0.221422 0.065996 0.676906 0.303648
php foreach - 0.052462 - 0.401962
python for 0.161213 0.122088 0.446916 0.454874
python numpy for 中止 0.14291 - -
python numpy method 0.002626 0.001414 0.000753 0.0003

 

多少恣意的ではありますがnumpyのすばらしさを分かっていただけたでしょうか。

 

機械学習などでnumpyを使うときはsum以外にも各種メソッドがありますのでそれを使うようにしましょう。