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

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

新規登録して質問してみよう
ただいま回答率
85.35%
深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

多次元配列

1次元配列内にさらに配列を格納している配列を、多次元配列と呼びます。

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

1回答

1858閲覧

[ゼロから作るDeepLearning]im2col関数における多次元配列同士の代入の仕組みが分からない

momendoufu

総合スコア10

深層学習

深層学習は、多数のレイヤのニューラルネットワークによる機械学習手法。人工知能研究の一つでディープラーニングとも呼ばれています。コンピューター自体がデータの潜在的な特徴を汲み取り、効率的で的確な判断を実現することができます。

多次元配列

1次元配列内にさらに配列を格納している配列を、多次元配列と呼びます。

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python

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

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

1クリップ

投稿2020/04/29 17:03

分からないこと

「ゼロから作るDeepLearning」という書籍を学習中です。
その第7章に畳み込みニューラルネットワークの解説がありim2colという関数が登場するのですが、その関数内で扱われる多次元配列(numpyのndarray型)同士の代入の動作が理解できません。

colという6次元の配列(np.zerosで生成)にimgという4次元配列(畳み込み層に対する入力データ)を代入する式に関して、
次元の小さい4次元配列がブロードキャストされて代入先と同じ6次元に拡張されるのは理解できるのですが、ブロードキャストのルールに則ると小さい方の次元の"先頭"に次元が追加されるらしく、そうなると代入元と代入先との次元の中身が異なってしまうのではと疑問に思っています。
具体的には、代入先の配列が(N, C, filter_h, filter_w, out_h, out_w)…①, 代入元が(N, C, h, w)なので代入元を拡張すると(N, C, N, C, h, w)…②となり、①と②の配列のそれぞれの次元の大きさが一致していない(特に3, 4次元目の部分)ように見えます。

これはそもそもブロードキャストの仕組みについての解釈が間違っているのでしょうか?
正しいとしても代入の仕組みがいまいち分かりません。

私自身多次元配列やCNNに詳しくないので前提などが間違っている可能性がありますが、何卒ご教示いただければ幸いです。

im2colのソースコード

python

1def im2col(input_data, filter_h, filter_w, stride=1, pad=0): 2 N, C, H, W = input_data.shape 3 out_h = (H + 2*pad - filter_h)//stride + 1 4 out_w = (W + 2*pad - filter_w)//stride + 1 5 6 img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant') 7 col = np.zeros((N, C, filter_h, filter_w, out_h, out_w)) # ここで代入先のゼロ配列を生成 8 9 for y in range(filter_h): 10 y_max = y + stride*out_h 11 for x in range(filter_w): 12 x_max = x + stride*out_w 13 col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride] 14 15 col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1) 16 return col

該当のソースコード

python

1col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]

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

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

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

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

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

guest

回答1

0

ベストアンサー

私もあまり自信はないのですが、この代入では次元を拡張するブロードキャストは行われていないと思います。

col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]の式で代入先になっている左辺のcol[:, :, y, x, :, :]は一見すると6次元に見えますが、実はもう4次元になっています。そのため、左右で次元数は揃った状態です。

なぜ6次元のcolが4次元になっているのかというと、3番目と4番目の指定をスライスではなくyxのスカラー値で指定しているためです。

以下、次元数が変わる簡単な例です。

python

1a = np.zeros((2,3,4)) 2print(a.shape) 3# (2, 3, 4) 4 5b = a[:, 1, :] 6print(b.shape) 7# (2, 4)  ←2次元になります!

以下、代入の例です。

Python

1a = np.zeros((2,3,4)) 2a[:, 1, :] = [[1, 2, 3, 4], [5, 6, 7, 8]] 3print(a) 4# [[[ 0. 0. 0. 0.] 5# [ 1. 2. 3. 4.] 6# [ 0. 0. 0. 0.]] 7# 8# [[ 0. 0. 0. 0.] 9# [ 5. 6. 7. 8.] 10# [ 0. 0. 0. 0.]]]

こちらの解説が参考になるかと思います。
NumPy配列ndarrayのスライスによる部分配列の選択と代入

投稿2020/04/30 02:48

編集2020/04/30 02:53
segavvy

総合スコア1038

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

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

momendoufu

2020/05/03 07:48

ご回答ありがとうございます! 長くて分かりにくい質問にも関わらず、まさに聞きたかったポイントを解説してくださり感動です。 この代入はブロードキャストではなかったのですね‥単純化してくださった具体例のおかげで疑問点が氷解しました。本当に助かりました。
segavvy

2020/05/03 08:05

お役に立てたようでよかったです!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問