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

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

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

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

Q&A

解決済

3回答

718閲覧

ゼロから作るDeep Leaningのクラスのコンストラクタの挙動

kontikuwa

総合スコア26

Python

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

0グッド

0クリップ

投稿2021/06/11 06:47

※全く同じ質問をしてる人がいるが、その答えだと全く理解できなかったためもう一度質問をさせていただいた。

ゼロから作るDeep Leaningの第五章
5.4.1 乗算レイヤの実装
のclass MulLayerのinit関数で、

python

1class MulLayer: 2 def __init__(self): 3 self.x = None # ここがわからない 4 self.y = None # ここがわからない 5 6  def forward(self, x, y): 7 self.x = x 8 self.y = y 9 out = self.x * self.y 10 11 return out 12 13 def backward(self, dout): 14 dx = dout * self.y 15 dy = dout * self.x 16 17 return dx, dy
def __init__(self): self.x = None self.y = None となっている理由は何ですか?

これ別にどうせ後でforward呼んだ時に更新しちゃうんで、Noneじゃなくて、10でも98でも8でも何でも良くないですか?

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

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

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

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

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

guest

回答3

0

自己解決

別に初期値はNoneじゃなくてもいい。

あとはこのページをよく読めば解決できるのではないかと思います。

あと初期値を

python

1def __init__(self, x, y): 2 self.x = x 3 self.y = y

のようにしないのは、最初の層だけはこれでもいい(なぜなら最初からx、yの値がわかっているから)のだが、2層目とか、3層目の時点ではインスタンス化する時にx,yの値がわかっていない(なぜなら、2層目のx、yは1層目の計算結果を元に作成される?から)ので、このようにしてはダメ。

インスタンス化する時点でx,yがわかっていないので、

python

1class MulLayer: 2 def __init__(self): 3 self.x = None 4 self.y = None

とするのが正解

投稿2021/06/12 20:50

kontikuwa

総合スコア26

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

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

0

ちなみにクラスの中に、def __init__を入れずに、インスタンスを呼び出した場合、エラーになりますね。

class MulLayer:

def forward(x,y): out=x*y return out def backward(dout): dx=dout*y dy=dout*x return dx,dy

mullayer=MulLayer()
mullayer.forward(1,2)

TypeError: forward() takes 2 positional arguments but 3 were given

投稿2021/06/11 08:05

okahijiki

総合スコア404

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

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

0

インスタンス変数として使用する属性名は__init__の中で列挙されているべき
という慣習があるからそう書くというだけの話です。

例えばこれらの行がない状態でコード解析器のpylint にかけると、"W0201 (attribute-defined-outside-init)" という警告があらわれます。

30年の歴史の中で培われてきたべからず集なので、書籍に書かれるコードなのであれば、それに従って書かれていることに特に不思議はありません。

(個人で書くコードで面倒だから要らない、と判断することは問題ないです。組織の中で書くコードは組織の慣習との相談でしょう)


10でも98でも8でも何でも良くないですか?

10や98や8だと、"利用者が間違った使い方をした時"にエラーにならない(可能性を残す)という欠陥があります。
フェイルファストの原則に従って、間違った使い方をしたら正しくエラーになる値にするべきで、それにはNoneが適しています。

投稿2021/06/11 07:14

編集2021/06/11 07:16
quickquip

総合スコア11235

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

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

kontikuwa

2021/06/11 07:20

ぶっちゃけちゃうと、Noneじゃなくてもいいってことですか?
quickquip

2021/06/11 07:24

Noneじゃなくてもいいですが、Noneが一番自然でしょう。 Noneは、こういうケースで使われるものとして定義されている値ですから。
quickquip

2021/06/11 07:32 編集

というか None を入れていたら(慣習によって)それで意図が通じるようになるわけですよ。 "慣習でそうなっている"ことの効能って、そういうところですよね。
quickquip

2021/06/11 07:47 編集

慣習云々とは別の系統の話で。 計算機科学分野で研究されてきた理論から、プログラミング言語にはこのような役割の型があった方とよい、というのが分かっています。 だから、他のプログラミング言語にも、ScalaならUnit型、RubyならNilClass型のように(名前は違っても)"役割は同じもの"が登場します。 そういう面から言っても、こういう所に使うならNoneが自然なのです。
okahijiki

2021/06/11 08:01

10や98や8を入れた場合、初期化に、何か思わせぶりがあるように思ってしまいませんかね。
quickquip

2021/06/11 08:18

そうですね。多分そこに10や98や8と書いてあったら質問者さんは今ここにこういう質問を書いていたでしょう。 self.y = 10 となっている理由は何ですか? と。 しかしその答えは、コードの中の他の箇所を読んで"値の意味"を読み解かない限りでてこないんです。 でもNoneであれば、Noneという値の方に"役割や意味が付いている"("意味が無い値"という意味があるという変な話ですが)ので、他の箇所を読まずとも"初期化子で属性名を確保したいだけだろう"という意図を読み取ることができるんです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問