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

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

ただいまの
回答率

88.91%

Python3 numpyの2次元配列同士の計算エラー

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 3,473

Hiroaki_N

score 7

前提・実現したいこと

Python3.5.2でニューラルネットワークを作っています。
勾配を数値微分を求める機能を実装中に以下のエラーメッセージが発生しました。

発生している問題・エラーメッセージ

unsupported operand type(s) for -: 'list' and 'list'

該当のソースコード

def numerical_gradient(f, w):
    h = 1e-4 # 0.0001
    grad = np.zeros_like(w)

    for idx in range(w.size):
        tmp_val = w[idx]
        w[idx] = tmp_val + h
        fwh1 = f(w) # f(w+h)
        w[idx] = tmp_val - h
        fwh2 = f(w) # f(w-h)
        grad[idx] = (fwh1- fwh2) / (2*h) # ここでエラーが発生しています
        w[idx] = tmp_val # 値を元に戻す

    return grad

class TwoLayerNet:

    def __init__(self, input_size, hidden_size, output_size, weight_init_std=0.01):
        # 重みの初期化
        self.params = {}
        self.params['w1'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['w2'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['w3'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['w4'] = weight_init_std * np.random.randn(input_size, hidden_size)
        self.params['w5'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['w6'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['w7'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['w8'] = weight_init_std * np.random.randn(hidden_size, output_size)
        self.params['b1'] = np.zeros(hidden_size)

    def predict(self, x):
        w1, w2, w3, w4, w5, w6, w7, w8 = self.params['w1'], self.params['w2'], self.params['w3'], self.params['w4'], self.params['w5'], self.params['w6'], self.params['w7'], self.params['w8']
        b1 = self.params['b1']
        z = []
        y = []

        a1 = np.dot(w1, x[0][0]) + np.dot(w2, x[0][1]) + np.dot(w3, x[0][2]) + np.dot(w4, x[0][3]) + b1
        z.append(np.dot(w5, a1))
        z.append(np.dot(w6, a1))
        z.append(np.dot(w7, a1))
        z.append(np.dot(w8, a1))
        y.append(softmax(z[0]))
        y.append(softmax(z[1]))
        y.append(softmax(z[2]))
        y.append(softmax(z[3]))
        return y
    # x:入力データ, t:教師データ
    def loss(self, x, t):
        y = self.predict(x)
        return y

    # x:入力データ, t:教師データ
    def numerical_gradient(self, x, t):
        #損失関数定義
        loss_W = lambda w: self.loss(x, t)
        #def loss_W(w):
        #   return self.loss(x, t)

        #勾配導出
        grads = {}
        grads['w1'] = numerical_gradient(loss_W, self.params['w1'])
        grads['w2'] = numerical_gradient(loss_W, self.params['w2'])
        grads['w3'] = numerical_gradient(loss_W, self.params['w3'])
        grads['w4'] = numerical_gradient(loss_W, self.params['w4'])
        grads['w5'] = numerical_gradient(loss_W, self.params['w5'])
        grads['w6'] = numerical_gradient(loss_W, self.params['w6'])
        grads['w7'] = numerical_gradient(loss_W, self.params['w7'])
        grads['w8'] = numerical_gradient(loss_W, self.params['w8'])
        grads['b1'] = numerical_gradient(loss_W, self.params['b1'])
        return grads

csv_obj = csv.reader(open("aaa.csv", "r"))
data = [ v for v in csv_obj]
x = [[0 for i in range(4)] for j in range(len(data))]#入力
t = [[0 for i in range(4)] for j in range(len(data)-1)]#教師データ
for i in range(len(data)):
    sss = str(data[i][1])
    x[i][0] = int(sss[0:1])
    x[i][1] = int(sss[1:2])
    x[i][2] = int(sss[2:3])
    x[i][3] = int(sss[3:4])

    if i >= 1:
        t[i-1][0] = int(sss[0:1])
        t[i-1][1] = int(sss[1:2])
        t[i-1][2] = int(sss[2:3])
        t[i-1][3] = int(sss[3:4])

#ハイパーパラメータ定義
iters_num = 10000
#train_size = x_train.shape[0]
#batch_size = 100
learning_rate = 0.1
#TwoLayerNetインスタンス生成
network = TwoLayerNet(input_size=4, hidden_size=1, output_size=4)

#勾配の計算
for i in range(iters_num):
    grad = network.numerical_gradient(x, t) #数値微分

以下エラー表示の内容です
C:\deep-learning\ch04>python two_layer_net_Numbers4.py
Traceback (most recent call last):
  File "two_layer_net_Numbers4.py", line 128, in <module>
    grad = network.numerical_gradient(x, t) #数値微分
  File "two_layer_net_Numbers4.py", line 64, in numerical_gradient
    grads['w1'] = numerical_gradient(loss_W, self.params['w1'])
  File "..\common\gradient.py", line 73, in numerical_gradient
    grad[idx] = (fwh1- fwh2) / (2*h)
TypeError: unsupported operand type(s) for -: 'list' and 'list'

試したこと

http://stackoverflow.com/questions/26685679/typeerror-unsupported-operand-types-for-list-and-list
によく似た問題が記載してありましたので、このサイト言うとおり
grad[idx] = (np.array(fwh1)- np.array(fwh2)) / (2*h)
と問題のコードを変更して実行してみた所
could not broadcast input array from shape(4,1,1) into shape(1)
というエラーが表示されてしまい、どうするべきかわからりませんでした。

おそらくデータ型があっていないのだと思いますが、どのようにすると計算ができるようになるのかを教えていただけたら嬉しいです。

補足情報(言語/FW/ツール等のバージョンなど)

Python3.5.2やnumpyはAnaconda4.2.0をダウンロードして使っています。
使用端末はwindows10のPCです

よろしくお願い致します

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

エラーメッセージが

TypeError: unsupported operand type(s) for -: 'list' and 'list'

となっておりますので、fwh1 および fwh2 が PythonのList型であることがエラーの原因なのではないでしょうか。(実現したい内容から推測すると、fwh1fwh2は本来 numpy配列 であるべきなのかと思います。)

ソースコードを見る限り、このfwh1(fwh2)は TwoLayerNet.predict() の戻り値から得られていますので、とりあえずこの関数の戻り値をnumpy配列になるように修正してみてはいかがでしょうか。

あくまでも今回のエラーを解決する手段であり、他のエラーが起こらないか・コード全体が問題なく動作するかに関しては確認しておりませんので言及できません。スミマセン

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/15 19:28

    z = []
    y = []となっていたのを
    z = np.array([0,0,0,0])
    y = np.array([0,0,0,0])
    というようにnumpy配列にしてみました!
    あと、配列の形状が異なっているというエラーが出ましたが、
    network = TwoLayerNet(input_size=1, hidden_size=1, output_size=1)
    として、wやbの配列を1*1行列にした所、エラーは解消されました!
    ありがとうございます。

    キャンセル

+1

修行中の身にて大外れでも低評価にしないでね。

最初のエラーメッセージはlistには引算(-)はないよといってますね。
fwh1とfwh2はpredictが配列を返しているためにリストになっていますね。
質問者の方がnumpy配列にしてみたところ今度は grad[idx] はshape(1)なので代入できないと言っていますね。

さてpredictが配列を返しているためにこのような事態になっていますが
意図としては外側のnumerical_gradient関数で4要素を同時に計算したいということしょうか?
いずれにせよpredictメソッドとnumerical_gradient関数のミスマッチが原因と思われます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/15 19:30

    z = []
    y = []となっていたのを
    z = np.array([0,0,0,0])
    y = np.array([0,0,0,0])
    というようにnumpy配列にしてみました!
    あと、配列の形状が異なっているというエラーが出ましたが、
    network = TwoLayerNet(input_size=1, hidden_size=1, output_size=1)
    として、wやbの配列を1*1行列にした所、エラーは解消されました!
    ありがとうございます。

    はい、4要素を同時に計算したいと考えています。
    それについてはこれから考えようと思っています。
    また何かありましたらよろしくお願い致します!

    キャンセル

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

  • ただいまの回答率 88.91%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る