5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NumPy配列のスライスが分かっていなくてはまった話

Posted at

経緯

機械学習アルゴリズムを試すために,OpenCVで画像を読み込むプログラムを書きました。

画像サイズは$512\times 512$ですが,必要な$256\times 256$の領域のみを切り出し,その外側は使いません。
画像は約14万枚あり,このすべてに同じように読み込んでから切り出し処理を行います。
以下に状況を再現できる程度に簡単化したコードを示します。(大量のメモリを消費するので実行の際は注意してください)

import numpy as np
import cv2

images = []
for i in range(140000):
    # 画像読み込み(のつもり)
    # 本当はcv2.imread()
    img = np.ones((512,512,3), dtype=np.uint8)
    img = img[:256, :256]    # 256x256の領域を切り出す
    images.append(img)

cv2.imread()で画像を読み込むと,符号なし8bit整数型のNumPy配列が返されます。
カラー画像なので,14万枚に対して切り出し処理まで行った場合,単純計算で

256\times 256\times 3\times 140000\;{\rm [B]} = 25.6\;{\rm [GB]}

の容量になります。
計算機のメモリは64GBなので十分余裕なはずですが・・・

足りませんでした

原因(?)

NumPyを分かっている人なら当然の話かもしれません。

NumPy配列(ndarray)に対してスライスで一部を切り出すと,新しい配列が生成されるわけではなく,viewと呼ばれる種類のndarrayが返されます。
viewはもとの配列とメモリ上の同じ領域を参照しているので,viewを変更するともとの配列の値も変更されます。

view
a = np.array([1,2,3,4,5])
b = a[1:4]
print(a) # => array([1,2,3,4,5])
print(b) # => array([2,3,4])
b[1] = 100
print(a) # => array([1,2,100,4,5])

さて,ここで最初のコードについて考えます。
画像から領域を切り出す際にスライスを使っていました。
つまり,リストimagesにはviewがappendされていきます。

この時,切り出した外側の領域はどうなったのでしょうか?
通常,参照されなくなった領域はGCによりそのうち開放されますが,スライスを用いた場合,切り出されなかった領域もメモリに残り続けるのではないかと考えました。

そこで以下のようにしてviewをコピーし新たな配列を生成したところ,メモリは余裕で足りました。消費量も大体予想通りになりました。

改善版
import numpy as np
import cv2

images = []
for i in range(140000):
    # 画像読み込み(のつもり)
    # 本当はcv2.imread()
    img = np.ones((512,512,3), dtype=np.uint8)
    img = img[:256, :256]    # 256x256の領域を切り出す
    img = np.array(img)    # コピーを生成する
    images.append(img)

必要な領域のみをコピーしたことで,元の$512\times 512\times 3$の配列は完全にどこからも参照されなくなり,開放されているのだと思われます。

おわりに

NumPyのviewについての勉強になりました。
原因については,スライス後にコピーしたら解決したという事実から推測したものなので,誤っている可能性もあります。
何かありましたらご指摘いただけると幸いです。

5
4
0

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
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?