Xmaster6y commited on
Commit
b8887b3
·
unverified ·
1 Parent(s): 7277ab2

input_encoding

Browse files
demo/interfaces/activations.py CHANGED
@@ -9,7 +9,7 @@ import gradio as gr
9
  import os
10
  import torch
11
 
12
- from lczerolens import LczeroBoard, LczeroModel, Lens
13
 
14
  from demo import constants
15
  from demo.utils import get_info
@@ -17,10 +17,10 @@ from demo.utils import get_info
17
  def get_model(model_name: str):
18
  return LczeroModel.from_onnx_path(os.path.join(constants.ONNX_MODEL_DIRECTORY, model_name))
19
 
20
- def get_activations(model: LczeroModel, board: LczeroBoard):
21
  lens = Lens.from_name("activation", "block\d/conv2/relu")
22
  with torch.no_grad():
23
- results = lens.analyse(model, board)
24
  return [results[f"block{i}/conv2/relu_output"][0] for i in range(len(results))]
25
 
26
  def get_board(game_pgn:str, board_fen:str):
@@ -62,28 +62,34 @@ def render_activations(board: LczeroBoard, activations, layer_index:int, channel
62
  )
63
  return f"{constants.FIGURE_DIRECTORY}/activations_board.svg", f"{constants.FIGURE_DIRECTORY}/activations_colorbar.svg"
64
 
65
- def initial_load(model_name: str, board_fen: str, game_pgn: str, layer_index: int, channel_index: int):
66
  model = get_model(model_name)
67
  board = get_board(game_pgn, board_fen)
68
- activations = get_activations(model, board)
69
  info = get_info(model, board)
70
  plots = render_activations(board, activations, layer_index, channel_index)
71
  return model, board, activations, info, *plots
72
 
73
- def on_board_change(model: LczeroModel, game_pgn: str, board_fen: str, layer_index: int, channel_index: int):
74
  board = get_board(game_pgn, board_fen)
75
- activations = get_activations(model, board)
76
  info = get_info(model, board)
77
  plots = render_activations(board, activations, layer_index, channel_index)
78
  return board, activations, info, *plots
79
 
80
- def on_model_change(model_name: str, board: LczeroBoard, layer_index: int, channel_index: int):
81
  model = get_model(model_name)
82
- activations = get_activations(model, board)
83
  info = get_info(model, board)
84
  plots = render_activations(board, activations, layer_index, channel_index)
85
  return model, activations, info, *plots
86
 
 
 
 
 
 
 
87
  with gr.Blocks() as interface:
88
  with gr.Row():
89
  with gr.Column():
@@ -102,6 +108,15 @@ with gr.Blocks() as interface:
102
  max_lines=1,
103
  value=chess.STARTING_FEN,
104
  )
 
 
 
 
 
 
 
 
 
105
  model_name = gr.Dropdown(
106
  label="Model",
107
  choices=constants.ONNX_MODEL_NAMES,
@@ -133,36 +148,42 @@ with gr.Blocks() as interface:
133
 
134
  interface.load(
135
  initial_load,
136
- inputs=[model_name, game_pgn, board_fen, layer_index, channel_index],
137
  outputs=[model, board, activations, info, image_board, colorbar],
138
  concurrency_limit=1,
139
  concurrency_id="trace_queue"
140
  )
141
  game_pgn.submit(
142
  on_board_change,
143
- inputs=[model, game_pgn, board_fen, layer_index, channel_index],
144
  outputs=[board, activations, info, image_board, colorbar],
145
  concurrency_id="trace_queue"
146
  )
147
  board_fen.submit(
148
  on_board_change,
149
- inputs=[model, game_pgn, board_fen, layer_index, channel_index],
150
  outputs=[board, activations, info, image_board, colorbar],
151
  concurrency_id="trace_queue"
152
  )
153
  model_name.change(
154
  on_model_change,
155
- inputs=[model_name, board, layer_index, channel_index],
156
  outputs=[model, activations, info, image_board, colorbar],
157
  concurrency_id="trace_queue"
158
  )
 
 
 
 
 
 
159
  layer_index.change(
160
  render_activations,
161
- inputs=[board, activations, layer_index, channel_index],
162
  outputs=[image_board, colorbar],
163
  )
164
  channel_index.change(
165
  render_activations,
166
- inputs=[board, activations, layer_index, channel_index],
167
  outputs=[image_board, colorbar],
168
  )
 
9
  import os
10
  import torch
11
 
12
+ from lczerolens import LczeroBoard, LczeroModel, Lens, InputEncoding
13
 
14
  from demo import constants
15
  from demo.utils import get_info
 
17
  def get_model(model_name: str):
18
  return LczeroModel.from_onnx_path(os.path.join(constants.ONNX_MODEL_DIRECTORY, model_name))
19
 
20
+ def get_activations(model: LczeroModel, board: LczeroBoard, input_encoding: InputEncoding):
21
  lens = Lens.from_name("activation", "block\d/conv2/relu")
22
  with torch.no_grad():
23
+ results = lens.analyse(model, board, model_kwargs={"input_encoding": input_encoding})
24
  return [results[f"block{i}/conv2/relu_output"][0] for i in range(len(results))]
25
 
26
  def get_board(game_pgn:str, board_fen:str):
 
62
  )
63
  return f"{constants.FIGURE_DIRECTORY}/activations_board.svg", f"{constants.FIGURE_DIRECTORY}/activations_colorbar.svg"
64
 
65
+ def initial_load(model_name: str, board_fen: str, game_pgn: str, input_encoding: InputEncoding, layer_index: int, channel_index: int):
66
  model = get_model(model_name)
67
  board = get_board(game_pgn, board_fen)
68
+ activations = get_activations(model, board, input_encoding)
69
  info = get_info(model, board)
70
  plots = render_activations(board, activations, layer_index, channel_index)
71
  return model, board, activations, info, *plots
72
 
73
+ def on_board_change(model: LczeroModel, game_pgn: str, board_fen: str, input_encoding: InputEncoding, layer_index: int, channel_index: int):
74
  board = get_board(game_pgn, board_fen)
75
+ activations = get_activations(model, board, input_encoding)
76
  info = get_info(model, board)
77
  plots = render_activations(board, activations, layer_index, channel_index)
78
  return board, activations, info, *plots
79
 
80
+ def on_model_change(model_name: str, board: LczeroBoard, input_encoding: InputEncoding, layer_index: int, channel_index: int):
81
  model = get_model(model_name)
82
+ activations = get_activations(model, board, input_encoding)
83
  info = get_info(model, board)
84
  plots = render_activations(board, activations, layer_index, channel_index)
85
  return model, activations, info, *plots
86
 
87
+ def on_input_encoding_change(model: LczeroModel, board: LczeroBoard, input_encoding: InputEncoding, layer_index: int, channel_index: int):
88
+ activations = get_activations(model, board, input_encoding)
89
+ info = get_info(model, board)
90
+ plots = render_activations(board, activations, layer_index, channel_index)
91
+ return activations, info, *plots
92
+
93
  with gr.Blocks() as interface:
94
  with gr.Row():
95
  with gr.Column():
 
108
  max_lines=1,
109
  value=chess.STARTING_FEN,
110
  )
111
+ input_encoding = gr.Radio(
112
+ label="Input encoding",
113
+ choices=[
114
+ ("classical", InputEncoding.INPUT_CLASSICAL_112_PLANE),
115
+ ("repeated", InputEncoding.INPUT_CLASSICAL_112_PLANE_REPEATED),
116
+ ("no history", InputEncoding.INPUT_CLASSICAL_112_PLANE_NO_HISTORY)
117
+ ],
118
+ value=InputEncoding.INPUT_CLASSICAL_112_PLANE,
119
+ )
120
  model_name = gr.Dropdown(
121
  label="Model",
122
  choices=constants.ONNX_MODEL_NAMES,
 
148
 
149
  interface.load(
150
  initial_load,
151
+ inputs=[model_name, game_pgn, board_fen, input_encoding, layer_index, channel_index],
152
  outputs=[model, board, activations, info, image_board, colorbar],
153
  concurrency_limit=1,
154
  concurrency_id="trace_queue"
155
  )
156
  game_pgn.submit(
157
  on_board_change,
158
+ inputs=[model, game_pgn, board_fen, input_encoding, layer_index, channel_index],
159
  outputs=[board, activations, info, image_board, colorbar],
160
  concurrency_id="trace_queue"
161
  )
162
  board_fen.submit(
163
  on_board_change,
164
+ inputs=[model, game_pgn, board_fen, input_encoding, layer_index, channel_index],
165
  outputs=[board, activations, info, image_board, colorbar],
166
  concurrency_id="trace_queue"
167
  )
168
  model_name.change(
169
  on_model_change,
170
+ inputs=[model_name, board, input_encoding, layer_index, channel_index],
171
  outputs=[model, activations, info, image_board, colorbar],
172
  concurrency_id="trace_queue"
173
  )
174
+ input_encoding.change(
175
+ on_input_encoding_change,
176
+ inputs=[model, board, input_encoding, layer_index, channel_index],
177
+ outputs=[activations, info, image_board, colorbar],
178
+ concurrency_id="trace_queue"
179
+ )
180
  layer_index.change(
181
  render_activations,
182
+ inputs=[board, activations, input_encoding, layer_index, channel_index],
183
  outputs=[image_board, colorbar],
184
  )
185
  channel_index.change(
186
  render_activations,
187
+ inputs=[board, activations, input_encoding, layer_index, channel_index],
188
  outputs=[image_board, colorbar],
189
  )
demo/interfaces/encodings.py CHANGED
@@ -7,11 +7,11 @@ import chess.pgn
7
  import io
8
  import gradio as gr
9
 
10
- from lczerolens.board import LczeroBoard
11
 
12
  from ..constants import FIGURE_DIRECTORY
13
 
14
- def make_render(game_pgn:str, board_fen:str, plane_index:int):
15
  if game_pgn:
16
  try:
17
  board = LczeroBoard()
@@ -30,10 +30,10 @@ def make_render(game_pgn:str, board_fen:str, plane_index:int):
30
  print(e)
31
  gr.Warning("Invalid FEN, using starting position.")
32
  board = LczeroBoard()
33
- return board, *make_board_plot(board, plane_index)
34
 
35
- def make_board_plot(board:LczeroBoard, plane_index:int):
36
- input_tensor = board.to_input_tensor()
37
  board.render_heatmap(
38
  input_tensor[plane_index].view(64),
39
  save_to=f"{FIGURE_DIRECTORY}/encodings.svg",
@@ -60,6 +60,15 @@ with gr.Blocks() as interface:
60
  max_lines=1,
61
  value=chess.STARTING_FEN,
62
  )
 
 
 
 
 
 
 
 
 
63
  with gr.Group():
64
  with gr.Row():
65
  plane_index = gr.Slider(
@@ -75,7 +84,7 @@ with gr.Blocks() as interface:
75
 
76
  state_board = gr.State(value=LczeroBoard())
77
 
78
- render_inputs = [game_pgn, board_fen, plane_index]
79
  render_outputs = [state_board, image_board, colorbar]
80
  interface.load(
81
  make_render,
@@ -92,8 +101,13 @@ with gr.Blocks() as interface:
92
  inputs=render_inputs,
93
  outputs=render_outputs,
94
  )
 
 
 
 
 
95
  plane_index.change(
96
  make_board_plot,
97
- inputs=[state_board, plane_index],
98
  outputs=[image_board, colorbar],
99
  )
 
7
  import io
8
  import gradio as gr
9
 
10
+ from lczerolens.board import LczeroBoard, InputEncoding
11
 
12
  from ..constants import FIGURE_DIRECTORY
13
 
14
+ def make_render(game_pgn:str, board_fen:str, input_encoding:InputEncoding, plane_index:int):
15
  if game_pgn:
16
  try:
17
  board = LczeroBoard()
 
30
  print(e)
31
  gr.Warning("Invalid FEN, using starting position.")
32
  board = LczeroBoard()
33
+ return board, *make_board_plot(board, input_encoding, plane_index)
34
 
35
+ def make_board_plot(board:LczeroBoard, input_encoding:InputEncoding, plane_index:int):
36
+ input_tensor = board.to_input_tensor(input_encoding)
37
  board.render_heatmap(
38
  input_tensor[plane_index].view(64),
39
  save_to=f"{FIGURE_DIRECTORY}/encodings.svg",
 
60
  max_lines=1,
61
  value=chess.STARTING_FEN,
62
  )
63
+ input_encoding = gr.Radio(
64
+ label="Input encoding",
65
+ choices=[
66
+ ("classical", InputEncoding.INPUT_CLASSICAL_112_PLANE),
67
+ ("repeated", InputEncoding.INPUT_CLASSICAL_112_PLANE_REPEATED),
68
+ ("no history", InputEncoding.INPUT_CLASSICAL_112_PLANE_NO_HISTORY)
69
+ ],
70
+ value=InputEncoding.INPUT_CLASSICAL_112_PLANE,
71
+ )
72
  with gr.Group():
73
  with gr.Row():
74
  plane_index = gr.Slider(
 
84
 
85
  state_board = gr.State(value=LczeroBoard())
86
 
87
+ render_inputs = [game_pgn, board_fen, input_encoding, plane_index]
88
  render_outputs = [state_board, image_board, colorbar]
89
  interface.load(
90
  make_render,
 
101
  inputs=render_inputs,
102
  outputs=render_outputs,
103
  )
104
+ input_encoding.change(
105
+ make_board_plot,
106
+ inputs=[state_board, input_encoding, plane_index],
107
+ outputs=[image_board, colorbar],
108
+ )
109
  plane_index.change(
110
  make_board_plot,
111
+ inputs=[state_board, input_encoding, plane_index],
112
  outputs=[image_board, colorbar],
113
  )
demo/interfaces/gradients.py CHANGED
@@ -8,7 +8,7 @@ import io
8
  import gradio as gr
9
  import os
10
 
11
- from lczerolens import LczeroBoard, LczeroModel, Lens
12
 
13
  from demo import constants
14
  from demo.utils import get_info
@@ -16,7 +16,7 @@ from demo.utils import get_info
16
  def get_model(model_name: str):
17
  return LczeroModel.from_onnx_path(os.path.join(constants.ONNX_MODEL_DIRECTORY, model_name))
18
 
19
- def get_gradients(model: LczeroModel, board: LczeroBoard, target: str):
20
  lens = Lens.from_name("gradient")
21
 
22
  def init_target(model):
@@ -25,7 +25,7 @@ def get_gradients(model: LczeroModel, board: LczeroBoard, target: str):
25
  else:
26
  wdl_index = {"win": 0, "draw": 1, "loss": 2}[target]
27
  return getattr(model, "output/wdl").output[:, wdl_index]
28
- results = lens.analyse(model, board, init_target=init_target)
29
 
30
  return results["input_grad"]
31
 
@@ -61,30 +61,35 @@ def render_gradients(board: LczeroBoard, gradients, average_over_planes:bool, be
61
  )
62
  return f"{constants.FIGURE_DIRECTORY}/gradients_board.svg", f"{constants.FIGURE_DIRECTORY}/gradients_colorbar.svg"
63
 
64
- def initial_load(model_name: str, board_fen: str, game_pgn: str, target: str, average_over_planes:bool, begin_average_index:int, end_average_index:int, plane_index: int):
65
  model = get_model(model_name)
66
  board = get_board(game_pgn, board_fen)
67
- gradients = get_gradients(model, board, target)
68
  info = get_info(model, board)
69
  plots = render_gradients(board, gradients, average_over_planes, begin_average_index, end_average_index, plane_index)
70
  return model, board, gradients, info, *plots
71
 
72
- def on_board_change(model: LczeroModel, game_pgn: str, board_fen: str, target: str, average_over_planes:bool, begin_average_index:int, end_average_index:int, plane_index: int):
73
  board = get_board(game_pgn, board_fen)
74
- gradients = get_gradients(model, board, target)
75
  info = get_info(model, board)
76
  plots = render_gradients(board, gradients, average_over_planes, begin_average_index, end_average_index, plane_index)
77
  return board, gradients, info, *plots
78
 
79
- def on_model_change(model_name: str, board: LczeroBoard, target: str, average_over_planes:bool, begin_average_index:int, end_average_index:int, plane_index: int):
80
  model = get_model(model_name)
81
- gradients = get_gradients(model, board, target)
82
  info = get_info(model, board)
83
  plots = render_gradients(board, gradients, average_over_planes, begin_average_index, end_average_index, plane_index)
84
  return model, gradients, info, *plots
85
 
86
- def on_target_change(model: LczeroModel, board: LczeroBoard, target: str, average_over_planes:bool, begin_average_index:int, end_average_index:int, plane_index: int):
87
- gradients = get_gradients(model, board, target)
 
 
 
 
 
88
  plots = render_gradients(board, gradients, average_over_planes, begin_average_index, end_average_index, plane_index)
89
  return gradients, *plots
90
 
@@ -106,6 +111,15 @@ with gr.Blocks() as interface:
106
  max_lines=1,
107
  value=chess.STARTING_FEN,
108
  )
 
 
 
 
 
 
 
 
 
109
  model_name = gr.Dropdown(
110
  label="Model",
111
  choices=constants.ONNX_MODEL_NAMES,
@@ -150,37 +164,43 @@ with gr.Blocks() as interface:
150
 
151
  interface.load(
152
  initial_load,
153
- inputs=[model_name, game_pgn, board_fen, target, average_over_planes, begin_average_index, end_average_index, plane_index],
154
  outputs=[model, board, gradients, info, image_board, colorbar],
155
  concurrency_id="trace_queue"
156
  )
157
  game_pgn.submit(
158
  on_board_change,
159
- inputs=[model, game_pgn, board_fen, target, average_over_planes, begin_average_index, end_average_index, plane_index],
160
  outputs=[board, gradients, info, image_board, colorbar],
161
  concurrency_id="trace_queue"
162
  )
163
  board_fen.submit(
164
  on_board_change,
165
- inputs=[model, game_pgn, board_fen, target, average_over_planes, begin_average_index, end_average_index, plane_index],
166
  outputs=[board, gradients, info, image_board, colorbar],
167
  concurrency_id="trace_queue"
168
  )
169
  model_name.change(
170
  on_model_change,
171
- inputs=[model_name, board, target, average_over_planes, begin_average_index, end_average_index, plane_index],
172
  outputs=[model, gradients, info, image_board, colorbar],
173
  concurrency_id="trace_queue"
174
  )
 
 
 
 
 
 
175
  target.change(
176
  on_target_change,
177
- inputs=[model, board, target, average_over_planes, begin_average_index, end_average_index, plane_index],
178
  outputs=[gradients, image_board, colorbar],
179
  concurrency_id="trace_queue"
180
  )
181
  for render_arg in [average_over_planes, begin_average_index, end_average_index, plane_index]:
182
  render_arg.change(
183
  render_gradients,
184
- inputs=[board, gradients, average_over_planes, begin_average_index, end_average_index, plane_index],
185
  outputs=[image_board, colorbar],
186
  )
 
8
  import gradio as gr
9
  import os
10
 
11
+ from lczerolens import LczeroBoard, LczeroModel, Lens, InputEncoding
12
 
13
  from demo import constants
14
  from demo.utils import get_info
 
16
  def get_model(model_name: str):
17
  return LczeroModel.from_onnx_path(os.path.join(constants.ONNX_MODEL_DIRECTORY, model_name))
18
 
19
+ def get_gradients(model: LczeroModel, board: LczeroBoard, input_encoding: InputEncoding, target: str):
20
  lens = Lens.from_name("gradient")
21
 
22
  def init_target(model):
 
25
  else:
26
  wdl_index = {"win": 0, "draw": 1, "loss": 2}[target]
27
  return getattr(model, "output/wdl").output[:, wdl_index]
28
+ results = lens.analyse(model, board, init_target=init_target, model_kwargs={"input_encoding": input_encoding})
29
 
30
  return results["input_grad"]
31
 
 
61
  )
62
  return f"{constants.FIGURE_DIRECTORY}/gradients_board.svg", f"{constants.FIGURE_DIRECTORY}/gradients_colorbar.svg"
63
 
64
+ def initial_load(model_name: str, board_fen: str, game_pgn: str, input_encoding: InputEncoding, target: str, average_over_planes:bool, begin_average_index:int, end_average_index:int, plane_index: int):
65
  model = get_model(model_name)
66
  board = get_board(game_pgn, board_fen)
67
+ gradients = get_gradients(model, board, input_encoding, target)
68
  info = get_info(model, board)
69
  plots = render_gradients(board, gradients, average_over_planes, begin_average_index, end_average_index, plane_index)
70
  return model, board, gradients, info, *plots
71
 
72
+ def on_board_change(model: LczeroModel, game_pgn: str, board_fen: str, input_encoding: InputEncoding, target: str, average_over_planes:bool, begin_average_index:int, end_average_index:int, plane_index: int):
73
  board = get_board(game_pgn, board_fen)
74
+ gradients = get_gradients(model, board, input_encoding, target)
75
  info = get_info(model, board)
76
  plots = render_gradients(board, gradients, average_over_planes, begin_average_index, end_average_index, plane_index)
77
  return board, gradients, info, *plots
78
 
79
+ def on_model_change(model_name: str, board: LczeroBoard, input_encoding: InputEncoding, target: str, average_over_planes:bool, begin_average_index:int, end_average_index:int, plane_index: int):
80
  model = get_model(model_name)
81
+ gradients = get_gradients(model, board, input_encoding, target)
82
  info = get_info(model, board)
83
  plots = render_gradients(board, gradients, average_over_planes, begin_average_index, end_average_index, plane_index)
84
  return model, gradients, info, *plots
85
 
86
+ def on_input_encoding_change(model: LczeroModel, board: LczeroBoard, input_encoding: InputEncoding, target: str, average_over_planes:bool, begin_average_index:int, end_average_index:int, plane_index: int):
87
+ gradients = get_gradients(model, board, input_encoding, target)
88
+ plots = render_gradients(board, gradients, average_over_planes, begin_average_index, end_average_index, plane_index)
89
+ return gradients, *plots
90
+
91
+ def on_target_change(model: LczeroModel, board: LczeroBoard, input_encoding: InputEncoding, target: str, average_over_planes:bool, begin_average_index:int, end_average_index:int, plane_index: int):
92
+ gradients = get_gradients(model, board, input_encoding, target)
93
  plots = render_gradients(board, gradients, average_over_planes, begin_average_index, end_average_index, plane_index)
94
  return gradients, *plots
95
 
 
111
  max_lines=1,
112
  value=chess.STARTING_FEN,
113
  )
114
+ input_encoding = gr.Radio(
115
+ label="Input encoding",
116
+ choices=[
117
+ ("classical", InputEncoding.INPUT_CLASSICAL_112_PLANE),
118
+ ("repeated", InputEncoding.INPUT_CLASSICAL_112_PLANE_REPEATED),
119
+ ("no history", InputEncoding.INPUT_CLASSICAL_112_PLANE_NO_HISTORY)
120
+ ],
121
+ value=InputEncoding.INPUT_CLASSICAL_112_PLANE,
122
+ )
123
  model_name = gr.Dropdown(
124
  label="Model",
125
  choices=constants.ONNX_MODEL_NAMES,
 
164
 
165
  interface.load(
166
  initial_load,
167
+ inputs=[model_name, game_pgn, board_fen, input_encoding, target, average_over_planes, begin_average_index, end_average_index, plane_index],
168
  outputs=[model, board, gradients, info, image_board, colorbar],
169
  concurrency_id="trace_queue"
170
  )
171
  game_pgn.submit(
172
  on_board_change,
173
+ inputs=[model, game_pgn, board_fen, input_encoding, target, average_over_planes, begin_average_index, end_average_index, plane_index],
174
  outputs=[board, gradients, info, image_board, colorbar],
175
  concurrency_id="trace_queue"
176
  )
177
  board_fen.submit(
178
  on_board_change,
179
+ inputs=[model, game_pgn, board_fen, input_encoding, target, average_over_planes, begin_average_index, end_average_index, plane_index],
180
  outputs=[board, gradients, info, image_board, colorbar],
181
  concurrency_id="trace_queue"
182
  )
183
  model_name.change(
184
  on_model_change,
185
+ inputs=[model_name, board, input_encoding, target, average_over_planes, begin_average_index, end_average_index, plane_index],
186
  outputs=[model, gradients, info, image_board, colorbar],
187
  concurrency_id="trace_queue"
188
  )
189
+ input_encoding.change(
190
+ on_input_encoding_change,
191
+ inputs=[model, board, input_encoding, target, average_over_planes, begin_average_index, end_average_index, plane_index],
192
+ outputs=[gradients, image_board, colorbar],
193
+ concurrency_id="trace_queue"
194
+ )
195
  target.change(
196
  on_target_change,
197
+ inputs=[model, board, input_encoding, target, average_over_planes, begin_average_index, end_average_index, plane_index],
198
  outputs=[gradients, image_board, colorbar],
199
  concurrency_id="trace_queue"
200
  )
201
  for render_arg in [average_over_planes, begin_average_index, end_average_index, plane_index]:
202
  render_arg.change(
203
  render_gradients,
204
+ inputs=[board, gradients, input_encoding, average_over_planes, begin_average_index, end_average_index, plane_index],
205
  outputs=[image_board, colorbar],
206
  )