

initializeでMiddleLayerとOutputlayerのクラスを継承？使用したいのですが、いまいちよくわからなくなってきてしまいました。  
目標としては、initializeのコンストラクタで、MiddlelayerとOutputlayerの層数（50，3）と（3，50）を変更するようにしたいのですが、２つのクラスの継承だと、どこでどうやって、super...を書けば良いかわからないです。  
プログラムは一応動きます。（クラスの部分は）

（あと、追加で実行して、OutputLayerのyを表示したいのですが、  
最後の二行を実行したときに、

[code]

    AttributeError: 'function' object has no attribute 'y'
    
[/code]

がでてしまいます。

### 追記

最後の二行の問題は改善しました）

[code]

    class initialize(MiddleLayer,OutputLayer):
        
        def __init__(self,data_input,data_correct,number_continu,eta):
            self.input = data_input
            self.correct = data_correct
            self.m = MiddleLayer(50,3)
            self.o = OutputLayer(3,50,0.1)        
            self.number_continu = number_continu
            self.middle_affine = np.random.randn(1, 3)
            self.output = np.random.randn(50) 
            self.eta = eta
        def learning(self):
            for i in range(self.number_continu):
                self.m.forward(self.input.reshape(1,50))
                self.middle_affine = self.m.y
                self.o.forward(self.m.y)
                self.output = self.o.y.reshape(-1)
                self.o.backward(self.correct.reshape(1,50))
                self.m.backward(self.o.grad_x)
                self.m.update(self.eta)
                self.o.update(self.eta)
        
        def plot_sin(self):
            fig = plt.figure()
            ax = fig.add_subplot(111)
            data = self.output
            ax.plot(data)
            
            plt.show()
    
    class MiddleLayer:
        def __init__(self, n_upper = 50, n =3,wb_width=0.1):
            self.w = wb_width * np.random.randn(n_upper, n)  # 重み（行列）
            self.b = wb_width * np.random.randn(n)  # バイアス（ベクトル）
        def forward(self, x):
            self.x = x
            self.u = np.dot(x, self.w) + self.b
            self.y = np.maximum(0, self.u)
    #        self.y = 1/(1+np.exp(-self.u))  # シグモイド関数
        def backward(self, grad_y):
            delta = grad_y * np.where(self.y <= 0, 0, 1)
    #        delta = grad_y * (1-self.y)*self.y        
            self.grad_w = np.dot(self.x.T, delta)
            self.grad_b = np.sum(delta, axis=0)
            self.grad_x = np.dot(delta, self.w.T) 
        def update(self, eta):
            self.w -= eta * self.grad_w
            self.b -= eta * self.grad_b
        
            
            
            
    # -- 出力層 --
    class OutputLayer:
        def __init__(self, n_upper = 3, n =50,wb_width = 0.1):
            self.w = wb_width * np.random.randn(n_upper, n)  # 重み（行列）
            self.b = wb_width * np.random.randn(n)  # バイアス（ベクトル）
        def forward(self, x):
            self.x = x
            u = np.dot(x, self.w) + self.b
            self.y = u  # 恒等関数
        def backward(self, t):
            delta = self.y - t
            self.grad_w = np.dot(self.x.T, delta)
            self.grad_b = np.sum(delta, axis=0)
            self.grad_x = np.dot(delta, self.w.T) 
        def update(self, eta):
            self.w -= eta * self.grad_w
            self.b -= eta * self.grad_b
    
    test = initialize(data_input,correct,1,0.1)
    test.learning()
    test.plot_sin()
    
[/code]


CC BY-SA 4.0
2020-12-12T09:05:26.463
72611
2020-12-21T05:59:13.640
2020-12-21T05:59:13.640
32986
37633
question
python
Python で 2 つの class を継承するとき、どこでどうやって super を書けば良いですか？


Pythonのクラスの多重継承については、@ITの[［Python入門］多重継承
(1/2)](https://www.atmarkit.co.jp/ait/articles/1908/27/news027.html)
の記事が判りやすいと思います。

「２つのクラスの継承だと、どこでどうやって、super...を書けば良いかわからないです」という疑問については、superで指定するのではなく、親クラス名を指定します。

[code]

    super.__init__(....)
    
[/code]

だと、どちらのクラスの __init__が呼び出されるか判りません(少なくとも判りやすいコードではない)が、

[code]

    MiddleLayer.__init__(....)
    
[/code]

だと、 MiddleLayerクラスの__init__が呼び出されるのが明白です。

＝＝  
多重継承で、複数の親クラスが同じ名前のメソッドを持つ(上記の__init__のように）場合に、どのクラスが優先されるかは、「C3線形化」というアルゴリズムで決められるそうです。


CC BY-SA 4.0
2020-12-12T12:18:53.470
72612
2020-12-12T16:39:13.450
2020-12-12T16:39:13.450
217
72611
answer