brendenc commited on
Commit
a596ffe
1 Parent(s): 001a3f2

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +291 -0
  2. requirements.txt +2 -0
app.py ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import keras
3
+ import numpy as np
4
+
5
+ # All reshaping layers and their args, descriptions
6
+ layers = {
7
+ "Reshape":{
8
+ "args":["target_shape"],
9
+ "descriptions":["""target_shape: Target shape. Tuple of integers, does not include the
10
+ samples dimension (batch size)."""]
11
+ },
12
+ "Flatten":{
13
+ "args":["data_format"],
14
+ "descriptions":["""data_format: A string, one of channels_last (default) or channels_first. The ordering of the dimensions in the inputs.
15
+ channels_last corresponds to inputs with shape (batch, ..., channels) while channels_first corresponds to inputs with shape (batch, channels, ...).
16
+ It defaults to the image_data_format value found in your Keras config file at ~/.keras/keras.json.
17
+ If you never set it, then it will be "channels_last"."""]
18
+ },
19
+ "RepeatVector":{
20
+ "args":["n"],
21
+ "descriptions":["n: Integer, repetition factor."]
22
+ },
23
+ "Permute":{
24
+ "args":["dims"],
25
+ "descriptions":["""dims: Tuple of integers.
26
+ Permutation pattern does not include the samples dimension. Indexing starts at 1.
27
+ For instance, (2, 1) permutes the first and second dimensions of the input."""]
28
+ },
29
+ "Cropping1D":{
30
+ "args":["cropping"],
31
+ "descriptions":["""cropping: Int or tuple of int (length 2)
32
+ How many units should be trimmed off at the beginning and end of the cropping dimension (axis 1).
33
+ If a single int is provided, the same value will be used for both."""]
34
+ },
35
+ "Cropping2D":{
36
+ "args":["cropping", "data_format"],
37
+ "descriptions":["""cropping: Int, or tuple of 2 ints, or tuple of 2 tuples of 2 ints.
38
+ If int: the same symmetric cropping is applied to height and width.
39
+ If tuple of 2 ints: interpreted as two different symmetric cropping values for height and width: (symmetric_height_crop, symmetric_width_crop).
40
+ If tuple of 2 tuples of 2 ints: interpreted as ((top_crop, bottom_crop), (left_crop, right_crop))""",
41
+ """data_format: A string, one of channels_last (default) or channels_first. The ordering of the dimensions in the inputs.
42
+ channels_last corresponds to inputs with shape (batch_size, height, width, channels) while channels_first corresponds to inputs with shape
43
+ (batch_size, channels, height, width). It defaults to the image_data_format value found in your Keras config file at ~/.keras/keras.json.
44
+ If you never set it, then it will be "channels_last"."""],
45
+ },
46
+ "Cropping3D":{
47
+ "args":["cropping", "data_format"],
48
+ "descriptions":["""cropping: Int, or tuple of 3 ints, or tuple of 3 tuples of 2 ints.
49
+ If int: the same symmetric cropping is applied to depth, height, and width.
50
+ If tuple of 3 ints: interpreted as two different symmetric cropping values for depth, height, and width: (symmetric_dim1_crop, symmetric_dim2_crop, symmetric_dim3_crop).
51
+ If tuple of 3 tuples of 2 ints: interpreted as ((left_dim1_crop, right_dim1_crop), (left_dim2_crop, right_dim2_crop), (left_dim3_crop, right_dim3_crop))""",
52
+ """data_format: A string, one of channels_last (default) or channels_first. The ordering of the dimensions in the inputs. channels_last corresponds to inputs with shape
53
+ (batch_size, spatial_dim1, spatial_dim2, spatial_dim3, channels) while channels_first corresponds to inputs with shape
54
+ (batch_size, channels, spatial_dim1, spatial_dim2, spatial_dim3). It defaults to the image_data_format value found in your Keras config file at ~/.keras/keras.json.
55
+ If you never set it, then it will be "channels_last"."""]
56
+ },
57
+ "UpSampling1D":{
58
+ "args":["size"],
59
+ "descriptions":["size: Integer. UpSampling factor."]
60
+ },
61
+ "UpSampling2D":{
62
+ "args":["size", "data_format", "interpolation"],
63
+ "descriptions":["size: Int, or tuple of 2 integers. The UpSampling factors for rows and columns.",
64
+ """data_format: A string, one of channels_last (default) or channels_first. The ordering of the dimensions in the inputs.
65
+ channels_last corresponds to inputs with shape (batch_size, height, width, channels) while channels_first corresponds to inputs with
66
+ shape (batch_size, channels, height, width). It defaults to the image_data_format value found in your Keras config file at ~/.keras/keras.json.
67
+ If you never set it, then it will be "channels_last".""",
68
+ """interpolation: A string, one of "area", "bicubic", "bilinear", "gaussian", "lanczos3", "lanczos5", "mitchellcubic", "nearest"."""]
69
+ },
70
+ "UpSampling3D":{
71
+ "args":["size","data_format"],
72
+ "descriptions":["size: Int, or tuple of 3 integers. The UpSampling factors for dim1, dim2 and dim3.",
73
+ """data_format: A string, one of channels_last (default) or channels_first. The ordering of the dimensions in the inputs.
74
+ channels_last corresponds to inputs with shape (batch_size, spatial_dim1, spatial_dim2, spatial_dim3, channels) while
75
+ channels_first corresponds to inputs with shape (batch_size, channels, spatial_dim1, spatial_dim2, spatial_dim3).
76
+ It defaults to the image_data_format value found in your Keras config file at ~/.keras/keras.json. If you never set it,
77
+ then it will be "channels_last"."""]
78
+ },
79
+ "ZeroPadding1D":{
80
+ "args":["padding"],
81
+ "descriptions":["""padding: Int, or tuple of int (length 2), or dictionary. - If int:
82
+ How many zeros to add at the beginning and end of the padding dimension (axis 1). -
83
+ If tuple of int (length 2): How many zeros to add at the beginning and the end of the padding dimension ((left_pad, right_pad))."""]
84
+ },
85
+ "ZeroPadding2D":{
86
+ "args":["padding", "data_format"],
87
+ "descriptions":["""padding: Int, or tuple of 2 ints, or tuple of 2 tuples of 2 ints.
88
+ If int: the same symmetric padding is applied to height and width.
89
+ If tuple of 2 ints: interpreted as two different symmetric padding values for height and width: (symmetric_height_pad, symmetric_width_pad).
90
+ If tuple of 2 tuples of 2 ints: interpreted as ((top_pad, bottom_pad), (left_pad, right_pad))""",
91
+ """data_format: A string, one of channels_last (default) or channels_first. The ordering of the dimensions in the inputs.
92
+ channels_last corresponds to inputs with shape (batch_size, height, width, channels) while channels_first corresponds to inputs with shape
93
+ (batch_size, channels, height, width). It defaults to the image_data_format value found in your Keras config file at ~/.keras/keras.json.
94
+ If you never set it, then it will be "channels_last"."""]
95
+ },
96
+ "ZeroPadding3D":{
97
+ "args":["padding", "data_format"],
98
+ "descriptions":["""padding: Int, or tuple of 3 ints, or tuple of 3 tuples of 2 ints.
99
+ If int: the same symmetric padding is applied to height and width.
100
+ If tuple of 3 ints: interpreted as two different symmetric padding values for height and width: (symmetric_dim1_pad, symmetric_dim2_pad, symmetric_dim3_pad).
101
+ If tuple of 3 tuples of 2 ints: interpreted as ((left_dim1_pad, right_dim1_pad), (left_dim2_pad, right_dim2_pad), (left_dim3_pad, right_dim3_pad))""",
102
+ """data_format: A string, one of channels_last (default) or channels_first. The ordering of the dimensions in the inputs. channels_last corresponds to inputs
103
+ with shape (batch_size, spatial_dim1, spatial_dim2, spatial_dim3, channels) while channels_first corresponds to inputs with shape
104
+ (batch_size, channels, spatial_dim1, spatial_dim2, spatial_dim3). It defaults to the image_data_format value found in your Keras config file
105
+ at ~/.keras/keras.json. If you never set it, then it will be "channels_last"."""]
106
+ }
107
+ }
108
+ with gr.Blocks() as demo:
109
+ gr.Markdown(f'![Keras](https://res.cloudinary.com/crunchbase-production/image/upload/c_lpad,h_256,w_256,f_auto,q_auto:eco,dpr_1/x3gdrogoamvuvjemehbr)')
110
+ gr.Markdown("# Reshaping Layers")
111
+ gr.Markdown("""This app allows you to play with various Keras Reshaping layers, and is meant to be a
112
+ supplement to the documentation. You are free to change the layer, tensor/array shape, and arguments associated
113
+ with that layer. Execution will show you the command used as well as your resulting array/tensor.
114
+
115
+ Keras documentation can be found [here](https://keras.io/api/layers/reshaping_layers/).<br>
116
+ App built by [Brenden Connors](https://github.com/brendenconnors).<br>
117
+ Built using keras==2.9.0.
118
+
119
+ <br><br><br>""")
120
+
121
+ with gr.Row():
122
+ with gr.Column():
123
+ layers_dropdown = gr.Dropdown(choices=list(layers.keys()), value="Reshape", label="Keras Layer")
124
+ with gr.Box():
125
+ gr.Markdown("**Please enter desired shape.**")
126
+ desired_shape2d = gr.Dataframe(value = [[2,2]],
127
+ headers = ["Rows", "Columns"],
128
+ row_count=(1, 'fixed'),
129
+ col_count=(2, "fixed"),
130
+ datatype="number",
131
+ type = "numpy",
132
+ interactive=True,
133
+ visible = False
134
+ )
135
+
136
+ desired_shape3d = gr.Dataframe(value = [[2,2,0]],
137
+ headers = ["Rows", "Columns", "Depth/Channels"],
138
+ row_count=(1, 'fixed'),
139
+ col_count=(3, "fixed"),
140
+ datatype="number",
141
+ type = "numpy",
142
+ interactive=True,
143
+ visible = True
144
+ )
145
+
146
+ desired_shape4d = gr.Dataframe(value = [[2,2,2,0]],
147
+ headers = ["Rows", "Columns", "Depth", "Channels"],
148
+ row_count=(1, 'fixed'),
149
+ col_count=(4, "fixed"),
150
+ datatype="number",
151
+ type = "numpy",
152
+ interactive=True,
153
+ visible = False
154
+ )
155
+
156
+ button = gr.Button("Generate Tensor")
157
+ input_arr = gr.Textbox(label = "Input Tensor",
158
+ interactive = False,
159
+ value = np.array([[1,2],[3,4]]))
160
+ with gr.Box():
161
+ gr.Markdown("**Layer Args**")
162
+ with gr.Row():
163
+ arg1 = gr.Textbox(label='target_shape')
164
+ arg2 = gr.Textbox(label='arg2',visible=False)
165
+ arg3 = gr.Textbox(label='arg3',visible=False)
166
+ with gr.Row():
167
+ desc1 = gr.Textbox(label= '', value = layers["Reshape"]["descriptions"][0])
168
+ desc2 = gr.Textbox(label = '', visible=False)
169
+ desc3 = gr.Textbox(label = '', visible=False)
170
+ result_button = gr.Button("Execute")
171
+ with gr.Column():
172
+ output = gr.Textbox(label = 'Command Used')
173
+ output2 = gr.Textbox(label = 'Result')
174
+
175
+ def generate_arr(layer, data1, data2, data3):
176
+ """
177
+ Create Input tensor
178
+ """
179
+ if '1D' in layer:
180
+ data = data1[0]
181
+
182
+ elif '2D' in layer:
183
+ data = data2[0]
184
+
185
+ elif '3D' in layer:
186
+ data = data3[0]
187
+
188
+ elif layer=="RepeatVector":
189
+ data = data1[0]
190
+
191
+ else:
192
+ data = data2[0]
193
+
194
+
195
+ shape = tuple([int(x) for x in data if int(x)!=0])
196
+ elements = [x+1 for x in range(np.prod(shape))]
197
+ return np.array(elements).reshape(shape)
198
+
199
+
200
+ def add_dim(layer):
201
+ """
202
+ Adjust dimensions component dependent on layer type
203
+ """
204
+ if '1D' in layer:
205
+ return gr.DataFrame.update(visible=True), gr.DataFrame.update(visible=False), gr.DataFrame.update(visible=False)
206
+ elif '2D' in layer:
207
+ return gr.DataFrame.update(visible=False), gr.DataFrame.update(visible=True), gr.DataFrame.update(visible=False)
208
+ elif '3D' in layer:
209
+ return gr.DataFrame.update(visible=False), gr.DataFrame.update(visible=False), gr.DataFrame.update(visible=True)
210
+ elif layer=="RepeatVector":
211
+ return gr.DataFrame.update(visible=True), gr.DataFrame.update(visible=False), gr.DataFrame.update(visible=False)
212
+ return gr.DataFrame.update(visible=False), gr.DataFrame.update(visible=True), gr.DataFrame.update(visible=False)
213
+
214
+
215
+ def change_args(layer):
216
+ """
217
+ Change layer args dependent on layer name
218
+ """
219
+ n_args = len(layers[layer]["args"])
220
+ args = layers[layer]["args"]
221
+ descriptions = layers[layer]["descriptions"]
222
+ descriptions = descriptions + ['None']*3
223
+ args = args + ['None']*3
224
+ visible_bool = [True if i<=n_args else False for i in range(1,4)]
225
+ return gr.Textbox.update(label=args[0], visible=visible_bool[0]),\
226
+ gr.Textbox.update(label=args[1], visible=visible_bool[1]),\
227
+ gr.Textbox.update(label=args[2], visible=visible_bool[2]),\
228
+ gr.Textbox.update(value = descriptions[0], visible = visible_bool[0]),\
229
+ gr.Textbox.update(value = descriptions[1], visible = visible_bool[1]),\
230
+ gr.Textbox.update(value = descriptions[2], visible = visible_bool[2])
231
+
232
+ def create_layer(layer_name, arg1, arg2, arg3):
233
+ """
234
+ Create layer given layer name and args
235
+ """
236
+ args = [arg1, arg2, arg3]
237
+ real_args = [x for x in args if x != '']
238
+ arg_str = ','.join(real_args)
239
+
240
+ return f"keras.layers.{layer_name}({arg_str})"
241
+
242
+
243
+ def execute(layer_name, arg1, arg2, arg3, shape1, shape2, shape3):
244
+ """
245
+ Execute keras reshaping layer given input tensor
246
+ """
247
+ args = [arg1, arg2, arg3]
248
+ real_args = [x for x in args if x != '']
249
+ arg_str = ','.join(real_args)
250
+ try:
251
+ layer = eval(f"keras.layers.{layer_name}({arg_str})")
252
+ except Exception as e:
253
+ return f"Error: {e}"
254
+
255
+ def arr(data, layer_name):
256
+ if layer_name == "RepeatVector":
257
+ shape = tuple([int(x) for x in data[0] if int(x)!=0])
258
+ else:
259
+ shape = tuple([1] + [int(x) for x in data[0] if int(x)!=0])
260
+ elements = [x+1 for x in range(np.prod(shape))]
261
+ return np.array(elements).reshape(shape)
262
+
263
+ if '1D' in layer_name:
264
+ inp = arr(shape1, layer_name)
265
+ elif '2D' in layer_name:
266
+ inp = arr(shape2, layer_name)
267
+ elif '3D' in layer_name:
268
+ inp = arr(shape3, layer_name)
269
+ elif layer_name=="RepeatVector":
270
+ inp = arr(shape1, layer_name)
271
+ else:
272
+ inp = arr(shape2, layer_name)
273
+
274
+ try:
275
+ return layer(inp)
276
+ except Exception as e:
277
+ return e
278
+
279
+ # Generate tensor
280
+ button.click(generate_arr, [layers_dropdown, desired_shape2d, desired_shape3d, desired_shape4d], input_arr)
281
+
282
+ # All changes dependent on layer selected
283
+ layers_dropdown.change(add_dim, layers_dropdown, [desired_shape2d, desired_shape3d, desired_shape4d])
284
+ layers_dropdown.change(change_args, layers_dropdown, [arg1, arg2, arg3, desc1, desc2, desc3])
285
+ layers_dropdown.change(generate_arr, [layers_dropdown, desired_shape2d, desired_shape3d, desired_shape4d], input_arr)
286
+
287
+ # Show command used and execute it
288
+ result_button.click(create_layer, [layers_dropdown, arg1, arg2, arg3], output)
289
+ result_button.click(execute, [layers_dropdown, arg1, arg2, arg3, desired_shape2d, desired_shape3d, desired_shape4d], output2)
290
+
291
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ keras==2.9.0
2
+ numpy