-
Notifications
You must be signed in to change notification settings - Fork 24
/
RNN_generacion_nombres.py
133 lines (103 loc) · 4.82 KB
/
RNN_generacion_nombres.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import numpy as np
np.random.seed(5)
from keras.layers import Input, Dense, SimpleRNN
from keras.models import Model
from keras.optimizers import SGD
from keras.utils import to_categorical
from keras import backend as K
# 1. LECTURA DEL SET DE DATOS
# ===========================================================
nombres = open('nombres_dinosaurios.txt','r').read()
nombres = nombres.lower()
# Crear diccionario (listado de caracteres que no se repiten)
alfabeto = list(set(nombres))
tam_datos, tam_alfabeto = len(nombres), len(alfabeto)
print("En total hay %d caracteres, y el diccionario tiene un tamaño de %d caracteres." % (tam_datos, tam_alfabeto))
# Conversión de caracteres a índices y viceversa
car_a_ind = { car:ind for ind,car in enumerate(sorted(alfabeto))}
ind_a_car = { ind:car for ind,car in enumerate(sorted(alfabeto))}
#print(car_a_ind)
#print(ind_a_car)
# 2. MODELO
# ===========================================================
n_a = 25 # Número de unidades en la capa oculta
entrada = Input(shape=(None,tam_alfabeto))
a0 = Input(shape=(n_a,))
celda_recurrente = SimpleRNN(n_a, activation='tanh', return_state = True)
capa_salida = Dense(tam_alfabeto, activation='softmax')
salida = []
hs, _ = celda_recurrente(entrada, initial_state=a0)
salida.append(capa_salida(hs))
modelo = Model([entrada,a0],salida)
#modelo.summary()
opt = SGD(lr=0.0005)
modelo.compile(optimizer=opt, loss='categorical_crossentropy')
# 3. EJEMPLOS DE ENTRENAMIENTO
# ===========================================================
# Crear lista con ejemplos de entrenamiento y mezclarla aleatoriamente
with open("nombres_dinosaurios.txt") as f:
ejemplos = f.readlines()
ejemplos = [x.lower().strip() for x in ejemplos]
np.random.shuffle(ejemplos)
# Crear ejemplos de entrenamiento usando un generador
def train_generator():
while True:
# Tomar un ejemplo aleatorio
ejemplo = ejemplos[np.random.randint(0,len(ejemplos))]
# Convertir el ejemplo a representación numérica
X = [None] + [car_a_ind[c] for c in ejemplo]
# Crear "Y", resultado de desplazar "X" un caracter a la derecha
Y = X[1:] + [car_a_ind['\n']]
# Representar "X" y "Y" en formato one-hot
x = np.zeros((len(X),1,tam_alfabeto))
onehot = to_categorical(X[1:],tam_alfabeto).reshape(len(X)-1,1,tam_alfabeto)
x[1:,:,:] = onehot
y = to_categorical(Y,tam_alfabeto).reshape(len(X),tam_alfabeto)
# Activación inicial (matriz de ceros)
a = np.zeros((len(X), n_a))
yield [x, a], y
# 4. ENTRENAMIENTO
# ===========================================================
BATCH_SIZE = 80 # Número de ejemplos de entrenamiento a usar en cada iteración
NITS = 10000 # Número de iteraciones
for j in range(NITS):
historia = modelo.fit_generator(train_generator(), steps_per_epoch=BATCH_SIZE, epochs=1, verbose=0)
# Imprimir evolución del entrenamiento cada 1000 iteraciones
if j%1000 == 0:
print('\nIteración: %d, Error: %f' % (j, historia.history['loss'][0]) + '\n')
# 5. GENERACIÓN DE NOMBRES USANDO EL MODELO ENTRENADO
# ===========================================================
def generar_nombre(modelo,car_a_num,tam_alfabeto,n_a):
# Inicializar x y a con ceros
x = np.zeros((1,1,tam_alfabeto,))
a = np.zeros((1, n_a))
# Nombre generado y caracter de fin de linea
nombre_generado = ''
fin_linea = '\n'
car = -1
# Iterar sobre el modelo y generar predicción hasta tanto no se alcance
# "fin_linea" o el nombre generado llegue a los 50 caracteres
contador = 0
while (car != fin_linea and contador != 50):
# Generar predicción usando la celda RNN
a, _ = celda_recurrente(K.constant(x), initial_state=K.constant(a))
y = capa_salida(a)
prediccion = K.eval(y)
# Escoger aleatoriamente un elemento de la predicción (el elemento con
# con probabilidad más alta tendrá más opciones de ser seleccionado)
ix = np.random.choice(list(range(tam_alfabeto)),p=prediccion.ravel())
# Convertir el elemento seleccionado a caracter y añadirlo al nombre generado
car = ind_a_car[ix]
nombre_generado += car
# Crear x_(t+1) = y_t, y a_t = a_(t-1)
x = to_categorical(ix,tam_alfabeto).reshape(1,1,tam_alfabeto)
a = K.eval(a)
# Actualizar contador y continuar
contador += 1
# Agregar fin de línea al nombre generado en caso de tener más de 50 caracteres
if (contador == 50):
nombre_generado += '\n'
print(nombre_generado)
# Generar 100 ejemplos de nombres generados por el modelo ya entrenado
for i in range(100):
generar_nombre(modelo,car_a_ind,tam_alfabeto,n_a)