Spaces:
Runtime error
Runtime error
Upload 2 files
Browse files- app.py +291 -0
- 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'')
|
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
|