-
Notifications
You must be signed in to change notification settings - Fork 3
/
Autoencoder.py
165 lines (123 loc) · 5 KB
/
Autoencoder.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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# Autoencoder class
'''
A class defining a deep autoencoder.
The encoder/decoder is a deep belief network.
After pre-training, the model is unrolled into a keras model that
can then be tuned with minibatch gradient descent.
After training, one can compute encodings using the encode function.
'''
import numpy as np
import pandas as pd
import os.path
from RBM import *
from RBM_with_linear_hidden_units import *
from keras.layers import Input, Dense
from keras.models import Model
from keras import backend as K
learning_rate = 0.01
class Autoencoder:
kind = 'Autoencoder'
def __init__(self,layer_dims):
'''
Inputs:
- layer_dims = A list of the layer sizes, visible first, latent last
Note that the number of hidden layers in the unrolled autoencoder
will be twice the length of layer_dims.
'''
self.latent_dim = layer_dims[-1]
self.v_dim = layer_dims[0]
self.num_hidden_layers = len(layer_dims)-1
self.layer_dims = layer_dims
print("Layer dimensions:")
for i in range(self.num_hidden_layers+1):
print("Layer %i: %i"%(i,self.layer_dims[i]))
self.W = []
self.b = []
self.a = []
self.pretrained = False
return
@classmethod
def pretrained_from_file(cls,filename):
'''
Initialize with pretrained weights from a file.
Still needs to be unrolled.
'''
i = 0
weights = []
layer_dims = []
while os.path.isfile(filename+"_"+str(i)+"_a.csv"): # load the next layer's weights
weights.append(RBM.load_weights(filename+"_"+str(i))) # load the next dict of weights
layer_dims.append(np.shape(weights[i]['W'])[0])
i = i+1
layer_dims.append(np.shape(weights[i-1]['W'])[1])
rbm = cls(layer_dims)
for i in range(rbm.num_hidden_layers):
rbm.W.append(weights[i]['W'])
rbm.a.append(weights[i]['a'])
rbm.b.append(weights[i]['b'])
rbm.pretrained = True
return rbm
def pretrain(self,x,epochs,num_samples = 50000):
'''
Greedy layer-wise training
The last layer is a RBM with linear hidden units
shape(x) = (v_dim, number_of_examples)
'''
RBM_layers = []
for i in range(self.num_hidden_layers): # initialize RBM's
if (i < self.num_hidden_layers - 1):
RBM_layers.append(RBM(self.layer_dims[i],self.layer_dims[i+1]))
else:
RBM_layers.append(RBM_with_linear_hidden_units(self.layer_dims[i],self.layer_dims[i+1]))
for i in range(self.num_hidden_layers): # train RBM's
print("Training RBM layer %i"%(i+1))
RBM_layers[i].train(x,epochs) # train the ith RBM
if not(i == self.num_hidden_layers - 1): # generate samples to train next layer
_,x = RBM_layers[i].gibbs_sampling(2,num_samples)
self.W.append(RBM_layers[i].W) # save trained weights
self.b.append(RBM_layers[i].b)
self.a.append(RBM_layers[i].a)
self.pretrained = True
return
def unroll(self):
'''
Unrolls the pretrained RBM network into a DFF keras model
and sets hidden layer parameters to pretrained values.
Returns the keras model
'''
if self.pretrained == False:
print("Model not pretrained.")
return
# define keras model structure
inputs = Input(shape=(self.v_dim,))
x = inputs
# build encoder
for i in range(self.num_hidden_layers):
weights = [self.W[i],self.b[i].flatten()]
if (i == self.num_hidden_layers - 1):
x = Dense(self.layer_dims[i+1],
weights = weights)(x)
else:
x = Dense(self.layer_dims[i+1],
activation='sigmoid',
weights = weights)(x)
# build decoder
for i in range(self.num_hidden_layers):
weights = [self.W[self.num_hidden_layers-i-1].T,self.a[self.num_hidden_layers-i-1].flatten()]
x = Dense(self.layer_dims[self.num_hidden_layers-i-1],
activation='sigmoid',
weights = weights)(x)
return Model(inputs,x)
def save(self,filename):
'''
saves the pretrained weights. Saving and loading a keras model
after pretraining is better done directly to the self.autoencoder
object using the keras fnctions save() and load_model()
'''
if self.pretrained == True:
for i in range(self.num_hidden_layers):
weights = {"W":self.W[i],'a':self.a[i],'b':self.b[i]}
RBM.save_weights(weights,filename+"_"+str(i))
else:
print("No pretrained weights to save.")
return