@@ -533,4 +533,86 @@ def forward(self, x):
533533 x_normalized = autograd .div (autograd .sub (x , sub1 ), div1 )
534534 y = autograd .mul (self .Gamma , x_normalized )
535535 y = autograd .add (y , self .Beta )
536- return y
536+ return y
537+
538+ class Linear3D (layer .Layer ):
539+ """
540+ Generate a Linear3D operator
541+ """
542+
543+ # TODO: replace current with
544+ # def __init__(self, out_features, bias=True):
545+ def __init__ (self , out_features , * args , bias = False , ** kwargs ):
546+ """
547+ Args:
548+ ut_channels: int, the channel of output, also is the number of
549+ filters
550+ bias: bool
551+ """
552+ super (Linear3D , self ).__init__ ()
553+ self .out_features = out_features
554+
555+ # TODO: for backward compatibility, to remove
556+ if len (args ) > 0 :
557+ self .in_features = out_features
558+ self .out_features = args [0 ]
559+ if len (args ) > 1 :
560+ self .bias = args [1 ]
561+ else :
562+ self .bias = bias
563+
564+ def initialize (self , x ):
565+ self .in_features = x .shape [- 1 ]
566+ w_shape = (self .in_features , self .out_features )
567+ b_shape = (self .out_features ,)
568+
569+ self .W = Tensor (shape = w_shape ,
570+ dtype = x .dtype ,
571+ requires_grad = True ,
572+ stores_grad = True )
573+ std = math .sqrt (2.0 / (self .in_features + self .out_features ))
574+ self .W .gaussian (0.0 , std )
575+
576+ if self .bias :
577+ self .b = Tensor (shape = b_shape ,
578+ dtype = x .dtype ,
579+ requires_grad = True ,
580+ stores_grad = True )
581+ self .b .set_value (0.0 )
582+ else :
583+ self .b = None
584+
585+ def forward (self , x ):
586+ if self .b :
587+ self .device_check (x , self .W , self .b )
588+ self .dtype_check (x , self .W , self .b )
589+ else :
590+ self .device_check (x , self .W )
591+ self .dtype_check (x , self .W )
592+
593+ assert x .shape [- 1 ] == self .W .shape [0 ], (
594+ "Linear3D layer expects input features size %d received %d" %
595+ (self .W .shape [0 ], x .shape [- 1 ]))
596+
597+ ys = []
598+ batch = x .shape [0 ]
599+ for i in range (batch ):
600+ xi = autograd .squeeze (x [i ])
601+ yi = autograd .matmul (xi , self .W )
602+ if self .bias :
603+ yi = autograd .add_bias (yi , self .b , axis = 0 )
604+ yi = autograd .unsqueeze (yi , axis = [0 ])
605+ ys .append (yi )
606+ y = autograd .cat (ys , axis = 0 )
607+ return y
608+
609+ def get_params (self ):
610+ if self .bias :
611+ return {self .W .name : self .W , self .b .name : self .b }
612+ else :
613+ return {self .W .name : self .W }
614+
615+ def set_params (self , parameters ):
616+ self .W .copy_from (parameters [self .W .name ])
617+ if self .bias :
618+ self .b .copy_from (parameters [self .b .name ])
0 commit comments