質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

4692閲覧

ディープラーニング バッチ処理をする際にメモリが圧迫される

退会済みユーザー

退会済みユーザー

総合スコア0

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

3クリップ

投稿2017/06/04 14:09

編集2017/06/05 11:39

任意のフォルダを選んで、そのフォルダの中にある画像をバッチ処理したいと考えています

python

1from PIL import Image 2import os 3import numpy as np 4import pickle 5 6directory = "ディレクトリ" 7画像フォルダ = os.listdir(directory) 8 9image_batch = np.empty((0, 151353), int) 10 11for it in 画像フォルダ: 12 13 if it == "Thumbs.db": 14 continue 15 16 image_value = np.array(Image.open(directory + "/" + it)) 17 image_value = image_value.reshape(1, image_value.size) 18 image_batch = np.append(image_batch, image_value, axis=0) 19 20with open ("猫画像バッチ処理.py", "wb") as 猫画像バッチ: 21 pickle.dump(image_batch, 猫画像バッチ)

os.listdirとイテレ―ションでフォルダの中にある全ての画像にアクセスして
reshapeで配列を1次元に直したうえで、image_batchにappendしていき、最後にpickleを使って変数を保存するというプログラムです

image_batchの初期化方法はこちらのサイトを参考にさせていただきました
http://qiita.com/fist0/items/d0779ff861356dafaf95

一応これで望んでいる処理が出来そうなのですが、画像フォルダの中には、
2512013の画像が2万近くあるせいか、実行してしばらくすると、メモリが圧迫されて、パソコンが動かなくなってしまいます。

↓こんな感じで分割して保存していくというのも考えてはみたのですが

python

1from PIL import Image 2import os 3import numpy as np 4import pickle 5 6directory = "ディレクトリ" 7画像フォルダ = os.listdir(directory) 8 9image_batch = np.empty((0, 151353), int) 10 11image_number = 0 12分割数 = 500 13pickle_name = 1 14 15while image_number != len(画像フォルダ) - (1): 16 17 image_name = "/" + 画像フォルダ[image_number] 18 19 if image_name == "/Thumbs.db": 20 image_number +=1 21 continue 22 23 image_value = np.array(Image.open(directory + image_name)) 24 image_value = image_value.reshape(1, image_value.size) 25 26 append = np.append 27 image_batch = append(image_batch, image_value, axis=0) 28 29 #分割をしながら保存していくプログラム 30 if image_batch.shape[0] == 分割数: 31 32 with open("猫画像バッチ処理" + str(pickle_name) +".py", "wb") as バッチ処理: 33 pickle.dump(image_batch, バッチ処理) 34 35 pickle_name += 1 36 image_batch = np.delete(image_batch, range(0, image_batch.shape[0]), axis=0) 37 38 image_number +=1 39

これだとメモリの圧迫を回避しながら保存していく事が出来たのですが、今度はpickleを手作業で足していくという作業が必要になってしまいます...

python

1import numpy as np 2import pickle 3import os 4 5with open("猫画像バッチ処理完了.py", "rb") as 猫画像バッチ1: 6 x = pickle.load(猫画像バッチ1) 7 8#手作業で名前を変えながら一つ一つappendしていかなければならない 9with open("猫画像バッチ処理6.py", "rb") as 猫画像バッチ: 10 y = pickle.load(猫画像バッチ) 11 12x = np.append(x, y, axis=0) 13 14with open("猫画像バッチ処理完了.py", "wb") as n: 15 pickle.dump(x, n)

手作業になると、ミスも起きやすいので、極力避けたいと思っています

メモリの圧迫を防げて、かつ手作業を極力減らせるバッチ処理を行う方法や、皆さんがどのようにバッチ処理をしているかなど、お聞きしたいです><

また、メモリは8GBあります。

追記

python

1from PIL import Image 2import os 3import numpy as np 4import pickle 5 6image_batch = np.empty((0, 151353), int) 7 8with open("猫画像バッチ処理.py", "wb") as バッチ処理: 9 pickle.dump(image_batch, バッチ処理) 10 11directory = "ディレクトリ" 12画像フォルダ = os.listdir(directory) 13 14image_number = 0 15分割数 = 200 16setter = np.empty((0, 151353), int) 17 18while image_number != len(画像フォルダ) - (1): 19 20 image_name = "/" + 画像フォルダ[image_number] 21 22 if image_name == "/Thumbs.db": 23 image_number +=1 24 continue 25 26 image_value = np.array(Image.open(directory + image_name)) 27 image_value = image_value.reshape(1, image_value.size) 28 29 append = np.append 30 setter = append(setter, image_value, axis=0) 31 32 if setter.shape[0] == 分割数: 33 34 with open("猫画像バッチ処理.py", "rb") as バッチ処理: 35 image_batch = pickle.load(バッチ処理) 36 37 image_batch = append(image_batch, setter, axis=0) 38 39 with open("猫画像バッチ処理.py", "wb") as バッチ処理: 40 pickle.dump(image_batch, バッチ処理) 41 42 print(image_batch.shape) 43 del image_batch 44 45 setter = np.delete(setter, range(0, setter.shape[0]), axis=0) 46 47 image_number +=1 48 49image_batch = append(image_batch, setter, axis=0) 50 51with open("猫画像バッチ処理.py", "wb") as バッチ処理: 52 pickle.dump(image_batch, バッチ処理)

新たの別の事を試したので、一応記載しておきます。
初期化されてある、image_batchを予め、pickle化して保存しておきます。
変数を保持する為にsetterを用意し、そこに画像の配列をappendしていき、指定した分割数が溜まれば、pickle化されてあったimage_batchを開いて、setterに溜まった配列と連結させ、それをpickleで上書き保存します。
そしてメモリを確保する為に、delとnp.deletaを使って、image_batchとsetterを削除します。
これで少しずつappendしながら保存できるので、うまくいくかと思ったのですが、タスクマネージャーの動きを見る限り、どうやらpickleをloadする時に大きくメモリを使ってしまうようです
メモリを圧迫してしまうのはやむおえない事なのでしょうか...

※回答に対するコードです。
コメントに書くとインデントがずれる為、此方に書かせて頂きます
回答を参考に書いたコードです

python

1from PIL import Image 2import os 3import numpy as np 4import pickle 5 6directory = "ディレクトリ" 7画像フォルダ = os.listdir(directory) 8 9image_list = [] 10 11for it in 画像フォルダ: 12 13 if it == "Thumbs.db": 14 continue 15 16 image_value = np.array(Image.open(directory + "/" + it)) 17 image_value = image_value.reshape(image_value.size) 18 append = image_list.append 19 append(image_value) 20 21image_batch = np.array(image_list) 22 23print(image_batch.shape) 24with open ("猫画像バッチ処理.py", "wb") as 猫画像バッチ: 25 pickle.dump(image_batch, 猫画像バッチ)
退会済みユーザー👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

image_listにすべての画像を展開しているため、メモリが膨大に膨れ上がっているためです。

image_listに一旦貯めるのではなく、pickleに順次ダンプしていけばよいのではないでしょうか?

python

1import pickle 2import io 3 4s = io.BytesIO() 5for x in range(10): 6 s.write(pickle.dumps(x)) 7 8s.seek(0) 9 10while True: 11 try: 12 t = pickle.load(s) 13 except EOFError: 14 break 15 print(t)

上の例ではBytesIOに保存していますが、これをファイルにすればバッファに貯めることなく、順次ダンプできます。


追記

ファイルに書き込む場合は以下のようになります。

python

1import pickle 2 3with open("test.pickle", "wb") as fd: 4 for x in range(10): 5 fd.write(pickle.dumps(x)) 6 7with open("test.pickle", "rb") as fd: 8 while True: 9 try: 10 t = pickle.load(fd) 11 except EOFError: 12 break 13 14 print(t)

投稿2017/06/06 00:25

編集2017/06/22 05:42
pashango2

総合スコア930

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/06/08 08:39

ありがとうございます! ioというのが何かわからなかったのでざっと調べた感じ、バイナリ化する?ものなのですかね。 バイナリ関連はほどんとした事ないですが、試してみます!
pashango2

2017/06/08 11:55

混乱させて申し訳ありません、s = io.BytesIO()はs = open("xxxx", "wb")に変換してください。 ioモジュールは処理の本筋ではありません。 BytesIOを使ったのは、単純にファイルを生成してしまうと後片付けが面倒だったためです。
退会済みユーザー

退会済みユーザー

2017/06/22 03:58

返信遅れてすいません これって順次ダンプする度に上書きしているように見えるのですがそうでもないのでしょうか? import pickle for i in range(10): >>>>with open("テスト.py", "wb") as テスト: >>>>>>>>pickle.dump(i, テスト) with open("テスト.py", "rb") as テスト: >>print(pickle.load(テスト)) インデントがずれるので代わりに>で表現させていただきました このコードでは、上書きされてしまいますが、提示してくださったコードとほぼ同義だと思うのですが、自分の理解が及んでないだけでしょうか
pashango2

2017/06/22 05:38

このコードでは上書きされます、openは1回だけです。
退会済みユーザー

退会済みユーザー

2017/06/22 06:10

コード拝見させていただきました。 理解するのに少し時間がかかりましたが、イテレータをpickleに保存して、イテレーションさせて取り出すという事をしているんですね こんなやり方があるとは...とても勉強になります><
guest

0

ベストアンサー

np.array に 1画像ずつ append する部分でメモリーを多く使ってしまっているのではと、想像します。
まずは、画像ごとの np.array を list にして、全部の画像をimage_listに入れてから、np.array(image_list) するというのは、如何でしょうか?

python

1image_list = [] 2 3for it in 画像フォルダ: 4 5 if it == "Thumbs.db": 6 continue 7 8 image_value = np.array(Image.open(directory + "/" + it)) 9 image_list.append(image_value.reshape(1, image_value.size)) 10 11image_batch=np.array(image_list)

投稿2017/06/05 09:47

hiro-k

総合スコア902

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/06/05 11:33

ありがとうございます! 試しにリストにappendしていき、最後にnp.arrayに変換してみましたが、結果は同じでした。 一応回答の方にコードを書いておきました
hiro-k

2017/06/05 11:36

フリーズに近い状態になるのって、 print(image_batch.shape) が表示される前ですか、それとも表示された後ですか? それによって、対応すべきところが変わるかと思います。
退会済みユーザー

退会済みユーザー

2017/06/05 11:42

表示される前ですね。 タスクマネージャーを確認しているのですが、少しずつメモリが圧迫されて、最終的にはハードディスクの法にも影響が出てメモリ、ディスクともに使用率が100%近くになります。
hiro-k

2017/06/05 12:01 編集

元のコードで1点気になるところがあります。 画像データは、251*201*3*2万 = 約2.8GB ですが、 image_batch = np.empty((0, 151353), int) と定義されているため、image_batch に append されると int型に変換されて、4倍 か 8倍に膨らみます。そうするとそのデータだけで実メモリサイズを越えてしまいます。これは意図されていることなのでしょうか? 私の提案した手法だと uint8 型が保持されるので、そこまでメモリは使われないはずですが、それでも固まるとなると、元コードは更に厳しいはずです。
退会済みユーザー

退会済みユーザー

2017/06/05 12:33

いえ int型に変換しているのは意図しているわけではなく、回答に貼ってあるurlのサイトには、intで書かれていた為、そうしただけです int型だと容量が大きく膨らむのは知りませんでした そして、試しにもう一度提示されたコードにprint(len(image_list))を追加して実行してみると、append部分はすんなり出来ていて、どうやらimage_listをnp.arrayに変換する時と、pickleを保存する際に大きな負荷がかかっていたようです。 なので、その部分で暫く待つと何とかpickleを保存する事が出来ました ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問