En Li Mu: Aprendizaje profundo práctico Capítulo 9 Sección 7: Aprendizaje de secuencia a secuencia (Seq2Seq), existe el siguiente código:
#@save
class Seq2SeqEncoder(d2l.Encoder):
"""用于序列到序列学习的循环神经网络编码器"""
def __init__(self, vocab_size, embed_size, num_hiddens, num_layers,
dropout=0, **kwargs):
super(Seq2SeqEncoder, self).__init__(**kwargs)
# 嵌入层
self.embedding = nn.Embedding(vocab_size, embed_size)
self.rnn = nn.GRU(embed_size, num_hiddens, num_layers,
dropout=dropout)
def forward(self, X, *args):
# 输出'X'的形状:(batch_size,num_steps,embed_size)
X = self.embedding(X)
# 在循环神经网络模型中,第一个轴对应于时间步
X = X.permute(1, 0, 2)
# 如果未提及状态,则默认为0
output, state = self.rnn(X)
# output的形状:(num_steps,batch_size,num_hiddens)
# state的形状:(num_layers,batch_size,num_hiddens)
return output, state
En la clase Seq2SeqEncoder, aparece super(Seq2SeqEncoder, self).__init__(**kwargs). Estoy un poco confundido acerca de para qué son las siguientes tres líneas de código. Para comprender estas tres líneas de código, debe comprender tres cosas :
- parámetro propio
- método __init__()
- super(Neto, propio).init()
A continuación, te explicaré uno por uno.
1. El autoparámetro
self se refiere a la instancia de la instancia en sí, en la clase de Python se estipula que el primer parámetro de la función es el objeto de la instancia en sí, y se acostumbra escribir su nombre como self, es decir, el primer parámetro del método en la clase debe ser uno mismo y no se puede omitir.
Creo que hay tres puntos importantes sobre uno mismo:
- self se refiere a la instancia en sí, no a la clase
- self puede ser reemplazado por esto, pero no escribas así
- El yo en el método de la clase no se puede omitir.
(1) self se refiere a la instancia en sí, no a la clase:
class Person():
def eat(self):
print(self)
Bob=Person() # 创建Person类的实例Bob
Bob.eat() # 调用eat
print(Person)
producción:
<__main__.Person object at 0x000002C383FBDA88> # Person类的实例Bob
<class '__main__.Person'> # Person是一个类
(2) self puede ser reemplazado por esto, pero generalmente no se escribe así:
class Person():
def eat(this):
print(this)
Bob=Person()
Bob.eat()
print(Person)
producción:
<__main__.Person object at 0x00000240E4C83908>
<class '__main__.Person'>
(3) No se puede omitir el self en el método de clase, el aviso en Pycharm:
Dos, método __init__ ()
Después de crear una clase en python, generalmente se crea un método __init__(), que se ejecuta automáticamente cuando se crea una instancia de la clase. El método __init__() debe contener un parámetro propio y debe ser el primer parámetro.
Por ejemplo, en el código del siguiente ejemplo, cuando se crea una instancia del objeto Bob, el método __init__ () se ha ejecutado automáticamente, pero si no es el método __init__ (), como el método eat (), entonces debe sólo puede llamarse implemento.
class Person():
def __init__(self):
print("是一个人")
def eat(self):
print("要吃饭" )
Bob=Person()
La salida llama automáticamente a la función de impresión en init:
是一个人
A continuación, agregamos otros parámetros en el método __init__, como pasar el nombre:
class Person():
def __init__(self,name):
print("是一个人")
self.name=name
def eat(self):
print("%s要吃饭" %self.name)
Bob=Person('Bob')
Bob.eat()
producción:
是一个人
Bob要吃饭
Nota: Después de proporcionar el nombre del parámetro en el método __init__, se debe especificar el nombre al crear una instancia de la clase; de lo contrario, se informará un error.
Bob=Person()
Bob.eat()
Dado que el método __init__ se puede llamar automáticamente, en realidad sabemos más claramente lo que se debe definir en el método __init__(), es decir, esperamos que algunas operaciones estén disponibles cuando se cree la instancia. Por ejemplo, el siguiente código debería definir la cantidad de dinero en el método __init__(), de modo que no sea necesario ejecutar el método qian() después de ejecutar el método eat(). O cuando escribimos el código de la red neuronal, es mejor poner algunas configuraciones de estructura de red en el método \__init__().
class Person():
def __init__(self,name):
print("是一个人")
self.name=name
def eat(self,money):
print("%s要吃饭" %self.name)
self.money=money
def qian(self):
print("花了%s元" %self.money)
Bob=Person('Bob')
Bob.eat(12)
Bob.qian()
Tres, super(Net, self).__init__()
super(Net, self).__init__() en Python se refiere a encontrar primero la clase principal de Net (por ejemplo, la clase NNet), luego convertir el objeto propio de la clase Net en un objeto de la clase NNet y luego la clase "convertida". NNet El objeto llama a su propia función init. De hecho, la comprensión simple es que la subclase coloca el __init__() de la clase principal en su propio __init__(), de modo que la subclase tiene el __init__() de la clase principal.
Mirando hacia atrás en nuestro código principal, la clase Seq2SeqEncoder hereda d2l.Encoder, super(Net, self).__init__() es para inicializar las propiedades heredadas de la clase principal d2l.Encoder. Y el método de inicialización de d2l.Encoder se usa para inicializar las propiedades heredadas. Es decir, la subclase hereda todas las propiedades y métodos de la clase principal, y las propiedades de la clase principal se inicializarán naturalmente con los métodos de la clase principal.
Déjame darte un ejemplo para ayudarte a entender:
class Person:
def __init__(self,name,gender):
self.name = name
self.gender = gender
def printinfo(self):
print(self.name,self.gender)
class Stu(Person):
def __init__(self,name,gender,school):
super(Stu, self).__init__(name,gender) # 使用父类的初始化方法来初始化子类
self.school = school
def printinfo(self): # 对父类的printinfo方法进行重写
print(self.name,self.gender,self.school)
if __name__ == '__main__':
stu = Stu('djk','man','nwnu')
stu.printinfo()
Por supuesto, si la lógica de inicialización es diferente a la de la clase principal, también es posible reinicializar por sí mismo sin utilizar el método de la clase principal. Por ejemplo:
class Person(object):
def __init__(self,name,gender,age):
self.name = name
self.gender = gender
self.age = age
class Student(Person):
def __init__(self,name,gender,age,school,score):
#super(Student,self).__init__(name,gender,age)
self.name = name.upper()
self.gender = gender.upper()
self.school = school
self.score = score
s = Student('Alice','female',18,'Middle school',87)
print s.school
print s.name