PhaseNet 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,175 @@
1
+ """Detect peaks in data based on their amplitude and other features."""
2
+
3
+ from __future__ import division, print_function
4
+ import numpy as np
5
+
6
+ __author__ = "Marcos Duarte, https://github.com/demotu/BMC"
7
+ __version__ = "1.0.4"
8
+ __license__ = "MIT"
9
+
10
+
11
+ def detect_peaks(x, mph=None, mpd=1, threshold=0, edge='rising',
12
+ kpsh=False, valley=False, show=False, ax=None):
13
+
14
+ """Detect peaks in data based on their amplitude and other features.
15
+
16
+ Parameters
17
+ ----------
18
+ x : 1D array_like
19
+ data.
20
+ mph : {None, number}, optional (default = None)
21
+ detect peaks that are greater than minimum peak height.
22
+ mpd : positive integer, optional (default = 1)
23
+ detect peaks that are at least separated by minimum peak distance (in
24
+ number of data).
25
+ threshold : positive number, optional (default = 0)
26
+ detect peaks (valleys) that are greater (smaller) than `threshold`
27
+ in relation to their immediate neighbors.
28
+ edge : {None, 'rising', 'falling', 'both'}, optional (default = 'rising')
29
+ for a flat peak, keep only the rising edge ('rising'), only the
30
+ falling edge ('falling'), both edges ('both'), or don't detect a
31
+ flat peak (None).
32
+ kpsh : bool, optional (default = False)
33
+ keep peaks with same height even if they are closer than `mpd`.
34
+ valley : bool, optional (default = False)
35
+ if True (1), detect valleys (local minima) instead of peaks.
36
+ show : bool, optional (default = False)
37
+ if True (1), plot data in matplotlib figure.
38
+ ax : a matplotlib.axes.Axes instance, optional (default = None).
39
+
40
+ Returns
41
+ -------
42
+ ind : 1D array_like
43
+ indeces of the peaks in `x`.
44
+
45
+ Notes
46
+ -----
47
+ The detection of valleys instead of peaks is performed internally by simply
48
+ negating the data: `ind_valleys = detect_peaks(-x)`
49
+
50
+ The function can handle NaN's
51
+
52
+ See this IPython Notebook [1]_.
53
+
54
+ References
55
+ ----------
56
+ .. [1] http://nbviewer.ipython.org/github/demotu/BMC/blob/master/notebooks/DetectPeaks.ipynb
57
+
58
+ Examples
59
+ --------
60
+ >>> from detect_peaks import detect_peaks
61
+ >>> x = np.random.randn(100)
62
+ >>> x[60:81] = np.nan
63
+ >>> # detect all peaks and plot data
64
+ >>> ind = detect_peaks(x, show=True)
65
+ >>> print(ind)
66
+
67
+ >>> x = np.sin(2*np.pi*5*np.linspace(0, 1, 200)) + np.random.randn(200)/5
68
+ >>> # set minimum peak height = 0 and minimum peak distance = 20
69
+ >>> detect_peaks(x, mph=0, mpd=20, show=True)
70
+
71
+ >>> x = [0, 1, 0, 2, 0, 3, 0, 2, 0, 1, 0]
72
+ >>> # set minimum peak distance = 2
73
+ >>> detect_peaks(x, mpd=2, show=True)
74
+
75
+ >>> x = np.sin(2*np.pi*5*np.linspace(0, 1, 200)) + np.random.randn(200)/5
76
+ >>> # detection of valleys instead of peaks
77
+ >>> detect_peaks(x, mph=0, mpd=20, valley=True, show=True)
78
+
79
+ >>> x = [0, 1, 1, 0, 1, 1, 0]
80
+ >>> # detect both edges
81
+ >>> detect_peaks(x, edge='both', show=True)
82
+
83
+ >>> x = [-2, 1, -2, 2, 1, 1, 3, 0]
84
+ >>> # set threshold = 2
85
+ >>> detect_peaks(x, threshold = 2, show=True)
86
+ """
87
+
88
+ x = np.atleast_1d(x).astype('float64')
89
+ if x.size < 3:
90
+ return np.array([], dtype=int)
91
+ if valley:
92
+ x = -x
93
+ # find indices of all peaks
94
+ dx = x[1:] - x[:-1]
95
+ # handle NaN's
96
+ indnan = np.where(np.isnan(x))[0]
97
+ if indnan.size:
98
+ x[indnan] = np.inf
99
+ dx[np.where(np.isnan(dx))[0]] = np.inf
100
+ ine, ire, ife = np.array([[], [], []], dtype=int)
101
+ if not edge:
102
+ ine = np.where((np.hstack((dx, 0)) < 0) & (np.hstack((0, dx)) > 0))[0]
103
+ else:
104
+ if edge.lower() in ['rising', 'both']:
105
+ ire = np.where((np.hstack((dx, 0)) <= 0) & (np.hstack((0, dx)) > 0))[0]
106
+ if edge.lower() in ['falling', 'both']:
107
+ ife = np.where((np.hstack((dx, 0)) < 0) & (np.hstack((0, dx)) >= 0))[0]
108
+ ind = np.unique(np.hstack((ine, ire, ife)))
109
+ # handle NaN's
110
+ if ind.size and indnan.size:
111
+ # NaN's and values close to NaN's cannot be peaks
112
+ ind = ind[np.in1d(ind, np.unique(np.hstack((indnan, indnan-1, indnan+1))), invert=True)]
113
+ # first and last values of x cannot be peaks
114
+ if ind.size and ind[0] == 0:
115
+ ind = ind[1:]
116
+ if ind.size and ind[-1] == x.size-1:
117
+ ind = ind[:-1]
118
+ # remove peaks < minimum peak height
119
+ if ind.size and mph is not None:
120
+ ind = ind[x[ind] >= mph]
121
+ # remove peaks - neighbors < threshold
122
+ if ind.size and threshold > 0:
123
+ dx = np.min(np.vstack([x[ind]-x[ind-1], x[ind]-x[ind+1]]), axis=0)
124
+ ind = np.delete(ind, np.where(dx < threshold)[0])
125
+ # detect small peaks closer than minimum peak distance
126
+ if ind.size and mpd > 1:
127
+ ind = ind[np.argsort(x[ind])][::-1] # sort ind by peak height
128
+ idel = np.zeros(ind.size, dtype=bool)
129
+ for i in range(ind.size):
130
+ if not idel[i]:
131
+ # keep peaks with the same height if kpsh is True
132
+ idel = idel | (ind >= ind[i] - mpd) & (ind <= ind[i] + mpd) \
133
+ & (x[ind[i]] > x[ind] if kpsh else True)
134
+ idel[i] = 0 # Keep current peak
135
+ # remove the small peaks and sort back the indices by their occurrence
136
+ ind = np.sort(ind[~idel])
137
+
138
+ if show:
139
+ if indnan.size:
140
+ x[indnan] = np.nan
141
+ if valley:
142
+ x = -x
143
+ _plot(x, mph, mpd, threshold, edge, valley, ax, ind)
144
+
145
+ return ind, x[ind]
146
+
147
+
148
+ def _plot(x, mph, mpd, threshold, edge, valley, ax, ind):
149
+ """Plot results of the detect_peaks function, see its help."""
150
+ try:
151
+ import matplotlib.pyplot as plt
152
+ except ImportError:
153
+ print('matplotlib is not available.')
154
+ else:
155
+ if ax is None:
156
+ _, ax = plt.subplots(1, 1, figsize=(8, 4))
157
+
158
+ ax.plot(x, 'b', lw=1)
159
+ if ind.size:
160
+ label = 'valley' if valley else 'peak'
161
+ label = label + 's' if ind.size > 1 else label
162
+ ax.plot(ind, x[ind], '+', mfc=None, mec='r', mew=2, ms=8,
163
+ label='%d %s' % (ind.size, label))
164
+ ax.legend(loc='best', framealpha=.5, numpoints=1)
165
+ ax.set_xlim(-.02*x.size, x.size*1.02-1)
166
+ ymin, ymax = x[np.isfinite(x)].min(), x[np.isfinite(x)].max()
167
+ yrange = ymax - ymin if ymax > ymin else 1
168
+ ax.set_ylim(ymin - 0.1*yrange, ymax + 0.1*yrange)
169
+ ax.set_xlabel('Data #', fontsize=14)
170
+ ax.set_ylabel('Amplitude', fontsize=14)
171
+ mode = 'Valley detection' if valley else 'Peak detection'
172
+ ax.set_title("%s (mph=%s, mpd=%d, threshold=%s, edge='%s')"
173
+ % (mode, str(mph), mpd, str(threshold), edge))
174
+ # plt.grid()
175
+ plt.show()
phasenet/model.py ADDED
@@ -0,0 +1,467 @@
1
+ import tensorflow as tf
2
+ # tf.compat.v1.disable_eager_execution()
3
+ import numpy as np
4
+ import logging
5
+
6
+ class ModelConfig:
7
+
8
+ batch_size = 20
9
+ depths = 5
10
+ filters_root = 8
11
+ kernel_size = [7, 1]
12
+ pool_size = [4, 1]
13
+ dilation_rate = [1, 1]
14
+ class_weights = [1.0, 1.0, 1.0]
15
+ loss_type = "cross_entropy"
16
+ weight_decay = 0.0
17
+ optimizer = "adam"
18
+ momentum = 0.9
19
+ learning_rate = 0.01
20
+ decay_step = 1e9
21
+ decay_rate = 0.9
22
+ drop_rate = 0.0
23
+ summary = True
24
+
25
+ X_shape = [3000, 1, 3]
26
+ n_channel = X_shape[-1]
27
+ Y_shape = [3000, 1, 3]
28
+ n_class = Y_shape[-1]
29
+
30
+ def __init__(self, **kwargs):
31
+ for k,v in kwargs.items():
32
+ setattr(self, k, v)
33
+
34
+ def update_args(self, args):
35
+ for k,v in vars(args).items():
36
+ setattr(self, k, v)
37
+
38
+
39
+ def crop_and_concat(net1, net2):
40
+ """
41
+ the size(net1) <= size(net2)
42
+ """
43
+ net1_shape = net1.get_shape().as_list()
44
+ net2_shape = net2.get_shape().as_list()
45
+ # print(net1_shape)
46
+ # print(net2_shape)
47
+ # if net2_shape[1] >= net1_shape[1] and net2_shape[2] >= net1_shape[2]:
48
+ offsets = [0, (net2_shape[1] - net1_shape[1]) // 2, (net2_shape[2] - net1_shape[2]) // 2, 0]
49
+ size = [-1, net1_shape[1], net1_shape[2], -1]
50
+ net2_resize = tf.slice(net2, offsets, size)
51
+ return tf.concat([net1, net2_resize], 3)
52
+ # else:
53
+ # offsets = [0, (net1_shape[1] - net2_shape[1]) // 2, (net1_shape[2] - net2_shape[2]) // 2, 0]
54
+ # size = [-1, net2_shape[1], net2_shape[2], -1]
55
+ # net1_resize = tf.slice(net1, offsets, size)
56
+ # return tf.concat([net1_resize, net2], 3)
57
+
58
+
59
+ def crop_only(net1, net2):
60
+ """
61
+ the size(net1) <= size(net2)
62
+ """
63
+ net1_shape = net1.get_shape().as_list()
64
+ net2_shape = net2.get_shape().as_list()
65
+ # print(net1_shape)
66
+ # print(net2_shape)
67
+ # if net2_shape[1] >= net1_shape[1] and net2_shape[2] >= net1_shape[2]:
68
+ offsets = [0, (net2_shape[1] - net1_shape[1]) // 2, (net2_shape[2] - net1_shape[2]) // 2, 0]
69
+ size = [-1, net1_shape[1], net1_shape[2], -1]
70
+ net2_resize = tf.slice(net2, offsets, size)
71
+ #return tf.concat([net1, net2_resize], 3)
72
+ return net2_resize
73
+
74
+ class UNet:
75
+ def __init__(self, config=ModelConfig(), input_batch=None, mode='train'):
76
+ self.depths = config.depths
77
+ self.filters_root = config.filters_root
78
+ self.kernel_size = config.kernel_size
79
+ self.dilation_rate = config.dilation_rate
80
+ self.pool_size = config.pool_size
81
+ self.X_shape = config.X_shape
82
+ self.Y_shape = config.Y_shape
83
+ self.n_channel = config.n_channel
84
+ self.n_class = config.n_class
85
+ self.class_weights = config.class_weights
86
+ self.batch_size = config.batch_size
87
+ self.loss_type = config.loss_type
88
+ self.weight_decay = config.weight_decay
89
+ self.optimizer = config.optimizer
90
+ self.learning_rate = config.learning_rate
91
+ self.decay_step = config.decay_step
92
+ self.decay_rate = config.decay_rate
93
+ self.momentum = config.momentum
94
+ self.global_step = tf.compat.v1.get_variable(name="global_step", initializer=0, dtype=tf.int32)
95
+ self.summary_train = []
96
+ self.summary_valid = []
97
+
98
+ self.build(input_batch, mode=mode)
99
+
100
+ def add_placeholders(self, input_batch=None, mode="train"):
101
+ if input_batch is None:
102
+ self.X = tf.compat.v1.placeholder(dtype=tf.float32, shape=[None, self.X_shape[-3], self.X_shape[-2], self.X_shape[-1]], name='X')
103
+ self.Y = tf.compat.v1.placeholder(dtype=tf.float32, shape=[None, self.Y_shape[-3], self.Y_shape[-2], self.n_class], name='y')
104
+ else:
105
+ self.X = input_batch[0]
106
+ if mode in ["train", "valid", "test"]:
107
+ self.Y = input_batch[1]
108
+ self.input_batch = input_batch
109
+
110
+ self.is_training = tf.compat.v1.placeholder(dtype=tf.bool, name="is_training")
111
+ # self.keep_prob = tf.compat.v1.placeholder(dtype=tf.float32, name="keep_prob")
112
+ self.drop_rate = tf.compat.v1.placeholder(dtype=tf.float32, name="drop_rate")
113
+
114
+ def add_prediction_op(self):
115
+ logging.info("Model: depths {depths}, filters {filters}, "
116
+ "filter size {kernel_size[0]}x{kernel_size[1]}, "
117
+ "pool size: {pool_size[0]}x{pool_size[1]}, "
118
+ "dilation rate: {dilation_rate[0]}x{dilation_rate[1]}".format(
119
+ depths=self.depths,
120
+ filters=self.filters_root,
121
+ kernel_size=self.kernel_size,
122
+ dilation_rate=self.dilation_rate,
123
+ pool_size=self.pool_size))
124
+
125
+ if self.weight_decay > 0:
126
+ weight_decay = tf.constant(self.weight_decay, dtype=tf.float32, name="weight_constant")
127
+ self.regularizer = tf.keras.regularizers.l2(l=0.5 * (weight_decay))
128
+ else:
129
+ self.regularizer = None
130
+
131
+ self.initializer = tf.compat.v1.keras.initializers.VarianceScaling(scale=1.0, mode="fan_avg", distribution="uniform")
132
+
133
+ # down sample layers
134
+ convs = [None] * self.depths # store output of each depth
135
+
136
+ with tf.compat.v1.variable_scope("Input"):
137
+ net = self.X
138
+ net = tf.compat.v1.layers.conv2d(net,
139
+ filters=self.filters_root,
140
+ kernel_size=self.kernel_size,
141
+ activation=None,
142
+ padding='same',
143
+ dilation_rate=self.dilation_rate,
144
+ kernel_initializer=self.initializer,
145
+ kernel_regularizer=self.regularizer,
146
+ name="input_conv")
147
+ net = tf.compat.v1.layers.batch_normalization(net,
148
+ training=self.is_training,
149
+ name="input_bn")
150
+ net = tf.nn.relu(net,
151
+ name="input_relu")
152
+ # net = tf.nn.dropout(net, self.keep_prob)
153
+ net = tf.compat.v1.layers.dropout(net,
154
+ rate=self.drop_rate,
155
+ training=self.is_training,
156
+ name="input_dropout")
157
+
158
+
159
+ for depth in range(0, self.depths):
160
+ with tf.compat.v1.variable_scope("DownConv_%d" % depth):
161
+ filters = int(2**(depth) * self.filters_root)
162
+
163
+ net = tf.compat.v1.layers.conv2d(net,
164
+ filters=filters,
165
+ kernel_size=self.kernel_size,
166
+ activation=None,
167
+ use_bias=False,
168
+ padding='same',
169
+ dilation_rate=self.dilation_rate,
170
+ kernel_initializer=self.initializer,
171
+ kernel_regularizer=self.regularizer,
172
+ name="down_conv1_{}".format(depth + 1))
173
+ net = tf.compat.v1.layers.batch_normalization(net,
174
+ training=self.is_training,
175
+ name="down_bn1_{}".format(depth + 1))
176
+ net = tf.nn.relu(net,
177
+ name="down_relu1_{}".format(depth+1))
178
+ net = tf.compat.v1.layers.dropout(net,
179
+ rate=self.drop_rate,
180
+ training=self.is_training,
181
+ name="down_dropout1_{}".format(depth + 1))
182
+
183
+ convs[depth] = net
184
+
185
+ if depth < self.depths - 1:
186
+ net = tf.compat.v1.layers.conv2d(net,
187
+ filters=filters,
188
+ kernel_size=self.kernel_size,
189
+ strides=self.pool_size,
190
+ activation=None,
191
+ use_bias=False,
192
+ padding='same',
193
+ dilation_rate=self.dilation_rate,
194
+ kernel_initializer=self.initializer,
195
+ kernel_regularizer=self.regularizer,
196
+ name="down_conv3_{}".format(depth + 1))
197
+ net = tf.compat.v1.layers.batch_normalization(net,
198
+ training=self.is_training,
199
+ name="down_bn3_{}".format(depth + 1))
200
+ net = tf.nn.relu(net,
201
+ name="down_relu3_{}".format(depth+1))
202
+ net = tf.compat.v1.layers.dropout(net,
203
+ rate=self.drop_rate,
204
+ training=self.is_training,
205
+ name="down_dropout3_{}".format(depth + 1))
206
+
207
+
208
+ # up layers
209
+ for depth in range(self.depths - 2, -1, -1):
210
+ with tf.compat.v1.variable_scope("UpConv_%d" % depth):
211
+ filters = int(2**(depth) * self.filters_root)
212
+ net = tf.compat.v1.layers.conv2d_transpose(net,
213
+ filters=filters,
214
+ kernel_size=self.kernel_size,
215
+ strides=self.pool_size,
216
+ activation=None,
217
+ use_bias=False,
218
+ padding="same",
219
+ kernel_initializer=self.initializer,
220
+ kernel_regularizer=self.regularizer,
221
+ name="up_conv0_{}".format(depth+1))
222
+ net = tf.compat.v1.layers.batch_normalization(net,
223
+ training=self.is_training,
224
+ name="up_bn0_{}".format(depth + 1))
225
+ net = tf.nn.relu(net,
226
+ name="up_relu0_{}".format(depth+1))
227
+ net = tf.compat.v1.layers.dropout(net,
228
+ rate=self.drop_rate,
229
+ training=self.is_training,
230
+ name="up_dropout0_{}".format(depth + 1))
231
+
232
+
233
+ #skip connection
234
+ net = crop_and_concat(convs[depth], net)
235
+ #net = crop_only(convs[depth], net)
236
+
237
+ net = tf.compat.v1.layers.conv2d(net,
238
+ filters=filters,
239
+ kernel_size=self.kernel_size,
240
+ activation=None,
241
+ use_bias=False,
242
+ padding='same',
243
+ dilation_rate=self.dilation_rate,
244
+ kernel_initializer=self.initializer,
245
+ kernel_regularizer=self.regularizer,
246
+ name="up_conv1_{}".format(depth + 1))
247
+ net = tf.compat.v1.layers.batch_normalization(net,
248
+ training=self.is_training,
249
+ name="up_bn1_{}".format(depth + 1))
250
+ net = tf.nn.relu(net,
251
+ name="up_relu1_{}".format(depth + 1))
252
+ net = tf.compat.v1.layers.dropout(net,
253
+ rate=self.drop_rate,
254
+ training=self.is_training,
255
+ name="up_dropout1_{}".format(depth + 1))
256
+
257
+
258
+ # Output Map
259
+ with tf.compat.v1.variable_scope("Output"):
260
+ net = tf.compat.v1.layers.conv2d(net,
261
+ filters=self.n_class,
262
+ kernel_size=(1,1),
263
+ activation=None,
264
+ padding='same',
265
+ #dilation_rate=self.dilation_rate,
266
+ kernel_initializer=self.initializer,
267
+ kernel_regularizer=self.regularizer,
268
+ name="output_conv")
269
+ # net = tf.nn.relu(net,
270
+ # name="output_relu")
271
+ # net = tf.compat.v1.layers.dropout(net,
272
+ # rate=self.drop_rate,
273
+ # training=self.is_training,
274
+ # name="output_dropout")
275
+ # net = tf.compat.v1.layers.batch_normalization(net,
276
+ # training=self.is_training,
277
+ # name="output_bn")
278
+ output = net
279
+
280
+ with tf.compat.v1.variable_scope("representation"):
281
+ self.representation = convs[-1]
282
+
283
+ with tf.compat.v1.variable_scope("logits"):
284
+ self.logits = output
285
+ tmp = tf.compat.v1.summary.histogram("logits", self.logits)
286
+ self.summary_train.append(tmp)
287
+
288
+ with tf.compat.v1.variable_scope("preds"):
289
+ self.preds = tf.nn.softmax(output)
290
+ tmp = tf.compat.v1.summary.histogram("preds", self.preds)
291
+ self.summary_train.append(tmp)
292
+
293
+ def add_loss_op(self):
294
+ if self.loss_type == "cross_entropy":
295
+ with tf.compat.v1.variable_scope("cross_entropy"):
296
+ flat_logits = tf.reshape(self.logits, [-1, self.n_class], name="logits")
297
+ flat_labels = tf.reshape(self.Y, [-1, self.n_class], name="labels")
298
+ if (np.array(self.class_weights) != 1).any():
299
+ class_weights = tf.constant(np.array(self.class_weights, dtype=np.float32), name="class_weights")
300
+ weight_map = tf.multiply(flat_labels, class_weights)
301
+ weight_map = tf.reduce_sum(input_tensor=weight_map, axis=1)
302
+ loss_map = tf.nn.softmax_cross_entropy_with_logits(logits=flat_logits,
303
+ labels=flat_labels)
304
+
305
+ weighted_loss = tf.multiply(loss_map, weight_map)
306
+ loss = tf.reduce_mean(input_tensor=weighted_loss)
307
+ else:
308
+ loss = tf.reduce_mean(input_tensor=tf.nn.softmax_cross_entropy_with_logits(logits=flat_logits,
309
+ labels=flat_labels))
310
+
311
+ elif self.loss_type == "IOU":
312
+ with tf.compat.v1.variable_scope("IOU"):
313
+ eps = 1e-7
314
+ loss = 0
315
+ for i in range(1, self.n_class):
316
+ intersection = eps + tf.reduce_sum(input_tensor=self.preds[:,:,:,i] * self.Y[:,:,:,i], axis=[1,2])
317
+ union = eps + tf.reduce_sum(input_tensor=self.preds[:,:,:,i], axis=[1,2]) + tf.reduce_sum(input_tensor=self.Y[:,:,:,i], axis=[1,2])
318
+ loss += 1 - tf.reduce_mean(input_tensor=intersection / union)
319
+ elif self.loss_type == "mean_squared":
320
+ with tf.compat.v1.variable_scope("mean_squared"):
321
+ flat_logits = tf.reshape(self.logits, [-1, self.n_class], name="logits")
322
+ flat_labels = tf.reshape(self.Y, [-1, self.n_class], name="labels")
323
+ with tf.compat.v1.variable_scope("mean_squared"):
324
+ loss = tf.compat.v1.losses.mean_squared_error(labels=flat_labels, predictions=flat_logits)
325
+ else:
326
+ raise ValueError("Unknown loss function: " % self.loss_type)
327
+
328
+ tmp = tf.compat.v1.summary.scalar("train_loss", loss)
329
+ self.summary_train.append(tmp)
330
+ tmp = tf.compat.v1.summary.scalar("valid_loss", loss)
331
+ self.summary_valid.append(tmp)
332
+
333
+ if self.weight_decay > 0:
334
+ with tf.compat.v1.name_scope('weight_loss'):
335
+ tmp = tf.compat.v1.get_collection(tf.compat.v1.GraphKeys.REGULARIZATION_LOSSES)
336
+ weight_loss = tf.add_n(tmp, name="weight_loss")
337
+ self.loss = loss + weight_loss
338
+ else:
339
+ self.loss = loss
340
+
341
+ def add_training_op(self):
342
+ if self.optimizer == "momentum":
343
+ self.learning_rate_node = tf.compat.v1.train.exponential_decay(learning_rate=self.learning_rate,
344
+ global_step=self.global_step,
345
+ decay_steps=self.decay_step,
346
+ decay_rate=self.decay_rate,
347
+ staircase=True)
348
+ optimizer = tf.compat.v1.train.MomentumOptimizer(learning_rate=self.learning_rate_node,
349
+ momentum=self.momentum)
350
+ elif self.optimizer == "adam":
351
+ self.learning_rate_node = tf.compat.v1.train.exponential_decay(learning_rate=self.learning_rate,
352
+ global_step=self.global_step,
353
+ decay_steps=self.decay_step,
354
+ decay_rate=self.decay_rate,
355
+ staircase=True)
356
+
357
+ optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=self.learning_rate_node)
358
+ update_ops = tf.compat.v1.get_collection(tf.compat.v1.GraphKeys.UPDATE_OPS)
359
+ with tf.control_dependencies(update_ops):
360
+ self.train_op = optimizer.minimize(self.loss, global_step=self.global_step)
361
+ tmp = tf.compat.v1.summary.scalar("learning_rate", self.learning_rate_node)
362
+ self.summary_train.append(tmp)
363
+
364
+ def add_metrics_op(self):
365
+ with tf.compat.v1.variable_scope("metrics"):
366
+
367
+ Y= tf.argmax(input=self.Y, axis=-1)
368
+ confusion_matrix = tf.cast(tf.math.confusion_matrix(
369
+ labels=tf.reshape(Y, [-1]),
370
+ predictions=tf.reshape(self.preds, [-1]),
371
+ num_classes=self.n_class, name='confusion_matrix'),
372
+ dtype=tf.float32)
373
+
374
+ # with tf.variable_scope("P"):
375
+ c = tf.constant(1e-7, dtype=tf.float32)
376
+ precision_P = (confusion_matrix[1,1] + c) / (tf.reduce_sum(input_tensor=confusion_matrix[:,1]) + c)
377
+ recall_P = (confusion_matrix[1,1] + c) / (tf.reduce_sum(input_tensor=confusion_matrix[1,:]) + c)
378
+ f1_P = 2 * precision_P * recall_P / (precision_P + recall_P)
379
+
380
+ tmp1 = tf.compat.v1.summary.scalar("train_precision_p", precision_P)
381
+ tmp2 = tf.compat.v1.summary.scalar("train_recall_p", recall_P)
382
+ tmp3 = tf.compat.v1.summary.scalar("train_f1_p", f1_P)
383
+ self.summary_train.extend([tmp1, tmp2, tmp3])
384
+
385
+ tmp1 = tf.compat.v1.summary.scalar("valid_precision_p", precision_P)
386
+ tmp2 = tf.compat.v1.summary.scalar("valid_recall_p", recall_P)
387
+ tmp3 = tf.compat.v1.summary.scalar("valid_f1_p", f1_P)
388
+ self.summary_valid.extend([tmp1, tmp2, tmp3])
389
+
390
+ # with tf.variable_scope("S"):
391
+ precision_S = (confusion_matrix[2,2] + c) / (tf.reduce_sum(input_tensor=confusion_matrix[:,2]) + c)
392
+ recall_S = (confusion_matrix[2,2] + c) / (tf.reduce_sum(input_tensor=confusion_matrix[2,:]) + c)
393
+ f1_S = 2 * precision_S * recall_S / (precision_S + recall_S)
394
+
395
+ tmp1 = tf.compat.v1.summary.scalar("train_precision_s", precision_S)
396
+ tmp2 = tf.compat.v1.summary.scalar("train_recall_s", recall_S)
397
+ tmp3 = tf.compat.v1.summary.scalar("train_f1_s", f1_S)
398
+ self.summary_train.extend([tmp1, tmp2, tmp3])
399
+
400
+ tmp1 = tf.compat.v1.summary.scalar("valid_precision_s", precision_S)
401
+ tmp2 = tf.compat.v1.summary.scalar("valid_recall_s", recall_S)
402
+ tmp3 = tf.compat.v1.summary.scalar("valid_f1_s", f1_S)
403
+ self.summary_valid.extend([tmp1, tmp2, tmp3])
404
+
405
+ self.precision = [precision_P, precision_S]
406
+ self.recall = [recall_P, recall_S]
407
+ self.f1 = [f1_P, f1_S]
408
+
409
+
410
+
411
+ def train_on_batch(self, sess, inputs_batch, labels_batch, summary_writer, drop_rate=0.0):
412
+ feed = {self.X: inputs_batch,
413
+ self.Y: labels_batch,
414
+ self.drop_rate: drop_rate,
415
+ self.is_training: True}
416
+
417
+ _, step_summary, step, loss = sess.run([self.train_op,
418
+ self.summary_train,
419
+ self.global_step,
420
+ self.loss],
421
+ feed_dict=feed)
422
+ summary_writer.add_summary(step_summary, step)
423
+ return loss
424
+
425
+ def valid_on_batch(self, sess, inputs_batch, labels_batch, summary_writer):
426
+ feed = {self.X: inputs_batch,
427
+ self.Y: labels_batch,
428
+ self.drop_rate: 0,
429
+ self.is_training: False}
430
+
431
+ step_summary, step, loss, preds = sess.run([self.summary_valid,
432
+ self.global_step,
433
+ self.loss,
434
+ self.preds],
435
+ feed_dict=feed)
436
+ summary_writer.add_summary(step_summary, step)
437
+ return loss, preds
438
+
439
+ def test_on_batch(self, sess, summary_writer):
440
+ feed = {self.drop_rate: 0,
441
+ self.is_training: False}
442
+ step_summary, step, loss, preds, \
443
+ X_batch, Y_batch, fname_batch, \
444
+ itp_batch, its_batch = sess.run([self.summary_valid,
445
+ self.global_step,
446
+ self.loss,
447
+ self.preds,
448
+ self.X,
449
+ self.Y,
450
+ self.input_batch[2],
451
+ self.input_batch[3],
452
+ self.input_batch[4]],
453
+ feed_dict=feed)
454
+ summary_writer.add_summary(step_summary, step)
455
+ return loss, preds, X_batch, Y_batch, fname_batch, itp_batch, its_batch
456
+
457
+
458
+ def build(self, input_batch=None, mode='train'):
459
+ self.add_placeholders(input_batch, mode)
460
+ self.add_prediction_op()
461
+ if mode in ["train", "valid", "test"]:
462
+ self.add_loss_op()
463
+ self.add_training_op()
464
+ # self.add_metrics_op()
465
+ self.summary_train = tf.compat.v1.summary.merge(self.summary_train)
466
+ self.summary_valid = tf.compat.v1.summary.merge(self.summary_valid)
467
+ return 0