Diff of /EEGLearn/model.py [000000] .. [117083]

Switch to unified view

a b/EEGLearn/model.py
1
##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2
## Created by: Yang Wang
3
## School of Automation, Huazhong University of Science & Technology (HUST)
4
## wangyang_sky@hust.edu.cn
5
## Copyright (c) 2018
6
##
7
## This source code is licensed under the MIT-style license found in the
8
## LICENSE file in the root directory of this source tree
9
##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10
11
#coding:utf-8
12
13
import tensorflow as tf
14
15
def my_conv2d(inputs, filters, kernel_size, strides=(1, 1), padding='same', activation=None, name=None, reuse=None):
16
    return tf.layers.conv2d(inputs=inputs, filters=filters, kernel_size=kernel_size, strides=strides, padding=padding, activation=activation,
17
                kernel_initializer=tf.truncated_normal_initializer(stddev=0.1), bias_initializer=tf.constant_initializer(0.1), name=name, reuse=reuse)
18
                
19
def build_cnn(input_image=None, image_size=32, n_colors=3, activation_function=tf.nn.relu, reuse=None, name='VGG_NET_CNN'):
20
    # VGG_NET 32       # [samples, W, H, colors]
21
    with tf.variable_scope(name, reuse=reuse): 
22
        input_image = tf.reshape(input_image, shape=[-1, image_size, image_size, n_colors], name='Reshape_inputs')
23
        # layer_1   # 4个3*3*32
24
        
25
        h_conv1_1 = my_conv2d(input_image, filters=32, kernel_size=(3,3), activation=activation_function, name='conv1_1')
26
        h_conv1_2 = my_conv2d(h_conv1_1, filters=32, kernel_size=(3,3), activation=activation_function, name='conv1_2')
27
        h_conv1_3 = my_conv2d(h_conv1_2, filters=32, kernel_size=(3,3), activation=activation_function, name='conv1_3')
28
        h_conv1_4 = my_conv2d(h_conv1_3, filters=32, kernel_size=(3,3), activation=activation_function, name='conv1_4')
29
        h_pool1 = tf.layers.max_pooling2d(h_conv1_4, pool_size=(2,2), strides=(2,2), padding='same', name='max_pooling_1')    # shape is (None, 16, 16, 32)
30
31
        # layer_2
32
        h_conv2_1 = my_conv2d(h_pool1, filters=64, kernel_size=(3,3), activation=activation_function, name='conv2_1')
33
        h_conv2_2 = my_conv2d(h_conv2_1, filters=64, kernel_size=(3,3), activation=activation_function, name='conv2_2')
34
        h_pool2 = tf.layers.max_pooling2d(h_conv2_2, pool_size=(2,2), strides=(2,2), padding='same', name='max_pooling_2')    # shape is (None, 8, 8, 64)
35
36
        # layer_3
37
        h_conv3_1 = my_conv2d(h_pool2, filters=128, kernel_size=(3,3), activation=activation_function, name='conv3_1')
38
        h_pool3 = tf.layers.max_pooling2d(h_conv3_1, pool_size=(2,2), strides=(2,2), padding='same', name='max_pooling_3')    # shape is (None, 4, 4, 128)
39
40
    return h_pool3
41
42
43
def build_convpool_max(input_image, nb_classes, image_size=32, n_colors=3, 
44
        n_timewin=7, dropout_rate=0.5, name='CNN_Max', train=True, reuse=False):
45
    """
46
    Builds the complete network with maxpooling layer in time.
47
48
    :param input_image: list of EEG images (one image per time window)
49
    :param nb_classes: number of classes
50
    :param image_size: size of the input image (assumes a square input)
51
    :param n_colors: number of color channels in the image
52
    :param n_timewin: number of time windows in the snippet
53
    :return: a pointer to the output of last layer
54
    """
55
    with tf.name_scope(name):
56
        with tf.name_scope('Parallel_CNNs'):
57
            convnets = []
58
            # Build 7 parallel CNNs with shared weights
59
            for i in range(n_timewin):
60
                if i==0:
61
                    convnet = build_cnn(input_image[i],image_size=image_size,n_colors=n_colors, reuse=reuse)
62
                else:
63
                    convnet = build_cnn(input_image[i],image_size=image_size,n_colors=n_colors, reuse=True)
64
                convnets.append(convnet)    # list contains [None, 4, 4, 128]
65
            convnets = tf.stack(convnets)   # [n_timewin, nSamples, 4, 4, 128]
66
            convnets = tf.transpose(convnets, [1,0,2,3,4]) # [nSamples, n_timewin, 4, 4, 128]
67
        
68
        with tf.variable_scope('Max_pooling_over_flames'):
69
            # convpooling using Max pooling over frames
70
            convnets = tf.reshape(convnets, shape=[ -1, n_timewin, 4*4*128, 1])
71
            convpool = tf.nn.max_pool(convnets, # [nSamples, 1,4*4*128, 1]
72
                ksize=[1, n_timewin, 1, 1], strides=[1, 1, 1, 1], padding='VALID', name='convpool_max')
73
        
74
75
        convpool_flat = tf.reshape(convpool, [-1, 4*4*128])
76
        h_fc1_drop1 = tf.layers.dropout(convpool_flat, rate=dropout_rate, training=train, name='dropout_1')
77
        # input shape [batch, 4*4*128] output shape [batch, 512]
78
        h_fc1 = tf.layers.dense(h_fc1_drop1, 512, activation=tf.nn.relu, name='fc_relu_512')
79
        # dropout 
80
        h_fc1_drop2 = tf.layers.dropout(h_fc1, rate=dropout_rate, training=train, name='dropout_2')
81
        # inputshape [batch, 512] output shape [batch, nb_classes]    # the loss function contains the softmax activation
82
        prediction = tf.layers.dense(h_fc1_drop2, nb_classes, name='fc_softmax')
83
    
84
    return prediction
85
86
def build_convpool_conv1d(input_image, nb_classes, image_size=32, n_colors=3, 
87
        n_timewin=7, dropout_rate=0.5, name='CNN_Conv1d', train=True, reuse=False):
88
    """
89
    Builds the complete network with 1D-conv layer to integrate time from sequences of EEG images.
90
91
    :param input_image: list of EEG images (one image per time window)
92
    :param nb_classes: number of classes
93
    :param image_size: size of the input image (assumes a square input)S
94
    :param n_colors: number of color channels in the image
95
    :param n_timewin: number of time windows in the snippet
96
    :return: a pointer to the output of last layer
97
    """
98
    with tf.name_scope(name):
99
        with tf.name_scope('Parallel_CNNs'):
100
            convnets = []
101
            # Build 7 parallel CNNs with shared weights
102
            for i in range(n_timewin):
103
                if i==0:
104
                    convnet = build_cnn(input_image[i],image_size=image_size,n_colors=n_colors, reuse=reuse)
105
                else:
106
                    convnet = build_cnn(input_image[i],image_size=image_size,n_colors=n_colors, reuse=True)
107
                convnets.append(convnet)
108
            convnets = tf.stack(convnets)
109
            convnets = tf.transpose(convnets, [1,0,2,3,4])
110
111
        with tf.variable_scope('Conv1d_over_flames'):
112
            convnets = tf.reshape(convnets, shape=[ -1, n_timewin, 4*4*128, 1])
113
            convpool = my_conv2d(convnets, filters=64, kernel_size=(3, 4*4*128), strides=(1, 1), padding='valid', activation=tf.nn.relu, name='convpool_conv1d')
114
115
116
        with tf.variable_scope('Output_layers'):
117
            convpool_flat = tf.reshape(convpool, [-1, (n_timewin-2)*64])
118
            h_fc1_drop1 = tf.layers.dropout(convpool_flat, rate=dropout_rate, training=train, name='dropout_1')
119
            h_fc1 = tf.layers.dense(h_fc1_drop1, 256, activation=tf.nn.relu, name='fc_relu_256')
120
            h_fc1_drop2 = tf.layers.dropout(h_fc1, rate=dropout_rate, training=train, name='dropout_2')
121
            prediction = tf.layers.dense(h_fc1_drop2, nb_classes, name='fc_softmax')
122
    
123
    return prediction
124
125
126
def build_convpool_lstm(input_image, nb_classes, grad_clip=110, image_size=32, n_colors=3, 
127
        n_timewin=7, dropout_rate=0.5, num_units=128, batch_size=32, name='CNN_LSTM', train=True, reuse=False):
128
    """
129
    Builds the complete network with LSTM layer to integrate time from sequences of EEG images.
130
131
    :param input_image: list of EEG images (one image per time window)
132
    :param nb_classes: number of classes
133
    :param grad_clip:  the gradient messages are clipped to the given value during
134
                        the backward pass.
135
    :param image_size: size of the input image (assumes a square input)
136
    :param n_colors: number of color channels in the image
137
    :param n_timewin: number of time windows in the snippet
138
    :param num_units: number of units in the LSTMCell
139
    :return: a pointer to the output of last layer
140
    """
141
    with tf.name_scope(name):
142
        with tf.name_scope('Parallel_CNNs'):
143
            convnets = []
144
            # Build 7 parallel CNNs with shared weights
145
            for i in range(n_timewin):
146
                if i==0:
147
                    convnet = build_cnn(input_image[i],image_size=image_size,n_colors=n_colors, reuse=reuse)
148
                else:
149
                    convnet = build_cnn(input_image[i],image_size=image_size,n_colors=n_colors, reuse=True)
150
                convnets.append(convnet)
151
            convnets = tf.stack(convnets)
152
            convnets = tf.transpose(convnets, [1,0,2,3,4]) # 调换轴 shape: (nSamples, n_timewin, 4, 4, 128)
153
154
        with tf.variable_scope('LSTM_layer'):
155
            # (nSamples, n_timewin, 4, 4, 128) ==>  (nSamples, n_timewin, 4*4*128)
156
            convnets = tf.reshape(convnets, shape=[-1, n_timewin, 4*4*128], name='Reshape_for_lstm')
157
            #lstm cell inputs:[batchs, time_steps, 4*4*128]
158
            with tf.variable_scope('LSTM_Cell'):
159
                lstm_cell = tf.contrib.rnn.BasicLSTMCell(num_units=num_units, forget_bias=1.0, state_is_tuple=True)
160
                outputs, final_state = tf.nn.dynamic_rnn(lstm_cell, convnets, dtype=tf.float32, time_major=False)
161
                # outputs.shape is (batch_size, time_steps, num_units)
162
                outputs = tf.transpose(outputs, [1,0,2])        # (time_steps, batch_size, num_units)
163
                outputs = outputs[-1]
164
165
        with tf.variable_scope('Output_layers'):
166
            h_fc1_drop1 = tf.layers.dropout(outputs, rate=dropout_rate, training=train, name='dropout_1')
167
            h_fc1 = tf.layers.dense(h_fc1_drop1, 256, activation=tf.nn.relu, name='fc_relu_256')
168
            h_fc1_drop2 = tf.layers.dropout(h_fc1, rate=dropout_rate, training=train, name='dropout_2')
169
            prediction = tf.layers.dense(h_fc1_drop2, nb_classes, name='fc_softmax')
170
171
    return prediction
172
173
174
def build_convpool_mix(input_image, nb_classes, grad_clip=110, image_size=32, n_colors=3, 
175
        n_timewin=7, dropout_rate=0.5, num_units=128, batch_size=32, name='CNN_Mix', train=True, reuse=False):
176
    """
177
    Builds the complete network with LSTM and 1D-conv layers combined
178
179
    :param input_image: list of EEG images (one image per time window)
180
    :param nb_classes: number of classes
181
    :param grad_clip:  the gradient messages are clipped to the given value during
182
                        the backward pass.
183
    :param imsize: size of the input image (assumes a square input)
184
    :param n_colors: number of color channels in the image
185
    :param n_timewin: number of time windows in the snippet
186
    :return: a pointer to the output of last layer
187
    """
188
    with tf.name_scope(name):
189
        with tf.name_scope('Parallel_CNNs'):
190
            convnets = []
191
            # Build 7 parallel CNNs with shared weights
192
            for i in range(n_timewin):
193
                if i==0:
194
                    convnet = build_cnn(input_image[i],image_size=image_size,n_colors=n_colors, reuse=reuse)
195
                else:
196
                    convnet = build_cnn(input_image[i],image_size=image_size,n_colors=n_colors, reuse=True)
197
                convnets.append(convnet)
198
            convnets = tf.stack(convnets)
199
            convnets = tf.transpose(convnets, [1,0,2,3,4])
200
201
        with tf.variable_scope('Conv1d_over_flames'):
202
            convpool = tf.reshape(convnets, shape=[ -1, n_timewin, 4*4*128, 1])
203
            convpool = my_conv2d(convpool, filters=64, kernel_size=(3, 4*4*128), strides=(1, 1), padding='valid', activation=tf.nn.relu, name='convpool_conv1d')
204
            conv1d_out = tf.reshape(convpool, [-1, (n_timewin-2)*64])
205
206
        with tf.variable_scope('LSTM_layer'):
207
            # (nSamples, n_timewin, 4, 4, 128) ==>  (nSamples, n_timewin, 4*4*128)
208
            convnets = tf.reshape(convnets, shape=[-1, n_timewin, 4*4*128], name='Reshape_for_lstm')
209
            #lstm cell inputs:[batchs, time_steps, 4*4*128]
210
            with tf.variable_scope('LSTM_Cell'):
211
                lstm_cell = tf.contrib.rnn.BasicLSTMCell(num_units=num_units, forget_bias=1.0, state_is_tuple=True)
212
                outputs, final_state = tf.nn.dynamic_rnn(lstm_cell, convnets, dtype=tf.float32, time_major=False)
213
                # outputs.shape is (batch_size, time_steps, num_units)
214
                outputs = tf.transpose(outputs, [1,0,2])
215
                lstm_out = outputs[-1]
216
217
        with tf.variable_scope('Output_layers'):
218
            dense_in = tf.concat((conv1d_out, lstm_out), axis=1, name='concat_conv1d_lstm')    # shape [batch, (n_timewin-2)*64+num_units]
219
            h_fc1_drop1 = tf.layers.dropout(dense_in, rate=dropout_rate, training=train, name='dropout_1')
220
            h_fc1 = tf.layers.dense(h_fc1_drop1, 512, activation=tf.nn.relu, name='fc_relu_512')
221
            h_fc1_drop2 = tf.layers.dropout(h_fc1, rate=dropout_rate, training=train, name='dropout_2')
222
            prediction = tf.layers.dense(h_fc1_drop2, nb_classes, name='fc_softmax')
223
224
    return prediction