Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
seminar-breakout
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Shashank Suhas
seminar-breakout
Commits
031dd698
You need to sign in or sign up before continuing.
Commit
031dd698
authored
Dec 26, 2015
by
ppwwyyxx
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
histogram summary
parent
bbe4faf4
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
182 additions
and
132 deletions
+182
-132
example_mnist.py
example_mnist.py
+22
-19
layers/regularize.py
layers/regularize.py
+22
-0
train.py
train.py
+1
-1
utils/callback.py
utils/callback.py
+23
-112
utils/validation_callback.py
utils/validation_callback.py
+114
-0
No files found.
example_mnist.py
View file @
031dd698
...
@@ -24,8 +24,8 @@ def get_model(inputs):
...
@@ -24,8 +24,8 @@ def get_model(inputs):
"""
"""
Args:
Args:
inputs: a list of input variable,
inputs: a list of input variable,
e.g.: [i
nput
_var, label_var] with:
e.g.: [i
mage
_var, label_var] with:
i
nput
_var: bx28x28
i
mage
_var: bx28x28
label_var: bx1 integer
label_var: bx1 integer
Returns:
Returns:
(outputs, cost)
(outputs, cost)
...
@@ -35,19 +35,18 @@ def get_model(inputs):
...
@@ -35,19 +35,18 @@ def get_model(inputs):
# use this variable in dropout! Tensorpack will automatically set it to 1 at test time
# use this variable in dropout! Tensorpack will automatically set it to 1 at test time
keep_prob
=
tf
.
placeholder
(
tf
.
float32
,
shape
=
tuple
(),
name
=
DROPOUT_PROB_OP_NAME
)
keep_prob
=
tf
.
placeholder
(
tf
.
float32
,
shape
=
tuple
(),
name
=
DROPOUT_PROB_OP_NAME
)
i
nput
,
label
=
inputs
i
mage
,
label
=
inputs
i
nput
=
tf
.
reshape
(
input
,
[
-
1
,
IMAGE_SIZE
,
IMAGE_SIZE
,
1
])
i
mage
=
tf
.
reshape
(
image
,
[
-
1
,
IMAGE_SIZE
,
IMAGE_SIZE
,
1
])
conv0
=
Conv2D
(
'conv0'
,
i
nput
,
out_channel
=
32
,
kernel_shape
=
5
,
conv0
=
Conv2D
(
'conv0'
,
i
mage
,
out_channel
=
32
,
kernel_shape
=
5
,
padding
=
'valid'
)
padding
=
'valid'
)
conv0
=
tf
.
nn
.
relu
(
conv0
)
conv0
=
tf
.
nn
.
relu
(
conv0
)
pool0
=
tf
.
nn
.
max_pool
(
conv0
,
ksize
=
[
1
,
2
,
2
,
1
],
strides
=
[
1
,
2
,
2
,
1
],
pool0
=
tf
.
nn
.
max_pool
(
conv0
,
ksize
=
[
1
,
2
,
2
,
1
],
padding
=
'SAME'
)
strides
=
[
1
,
2
,
2
,
1
],
padding
=
'SAME'
)
conv1
=
Conv2D
(
'conv1'
,
pool0
,
out_channel
=
40
,
kernel_shape
=
3
,
conv1
=
Conv2D
(
'conv1'
,
pool0
,
out_channel
=
40
,
kernel_shape
=
3
,
padding
=
'valid'
)
padding
=
'valid'
)
conv1
=
tf
.
nn
.
relu
(
conv1
)
conv1
=
tf
.
nn
.
relu
(
conv1
)
pool1
=
tf
.
nn
.
max_pool
(
conv1
,
ksize
=
[
1
,
2
,
2
,
1
],
strides
=
[
1
,
2
,
2
,
1
],
pool1
=
tf
.
nn
.
max_pool
(
conv1
,
ksize
=
[
1
,
2
,
2
,
1
],
padding
=
'SAME'
)
strides
=
[
1
,
2
,
2
,
1
],
padding
=
'SAME'
)
feature
=
batch_flatten
(
pool1
)
feature
=
batch_flatten
(
pool1
)
...
@@ -60,19 +59,23 @@ def get_model(inputs):
...
@@ -60,19 +59,23 @@ def get_model(inputs):
y
=
one_hot
(
label
,
10
)
y
=
one_hot
(
label
,
10
)
cost
=
tf
.
nn
.
softmax_cross_entropy_with_logits
(
fc1
,
y
)
cost
=
tf
.
nn
.
softmax_cross_entropy_with_logits
(
fc1
,
y
)
cost
=
tf
.
reduce_mean
(
cost
,
name
=
'cost'
)
cost
=
tf
.
reduce_mean
(
cost
)
#
number of correctly classified samples
#
compute the number of correctly classified samples, for ValidationAccuracy to use
correct
=
tf
.
equal
(
correct
=
tf
.
equal
(
tf
.
cast
(
tf
.
argmax
(
prob
,
1
),
tf
.
int32
),
label
)
tf
.
cast
(
tf
.
argmax
(
prob
,
1
),
tf
.
int32
),
label
)
correct
=
tf
.
reduce_sum
(
tf
.
cast
(
correct
,
tf
.
int32
),
name
=
'correct'
)
correct
=
tf
.
reduce_sum
(
tf
.
cast
(
correct
,
tf
.
int32
),
name
=
'correct'
)
return
[
prob
,
correct
],
cost
# weight decay on all W of fc layers
wd_cost
=
1e-4
*
regularize_cost
(
'fc.*/W'
,
tf
.
nn
.
l2_loss
)
return
[
prob
,
correct
],
tf
.
add
(
cost
,
wd_cost
,
name
=
'cost'
)
def
main
():
def
main
():
BATCH_SIZE
=
128
with
tf
.
Graph
()
.
as_default
():
with
tf
.
Graph
()
.
as_default
():
dataset_train
=
BatchData
(
Mnist
(
'train'
),
128
)
dataset_train
=
BatchData
(
Mnist
(
'train'
),
BATCH_SIZE
)
dataset_test
=
BatchData
(
Mnist
(
'test'
),
128
,
remainder
=
True
)
dataset_test
=
BatchData
(
Mnist
(
'test'
),
256
,
remainder
=
True
)
sess_config
=
tf
.
ConfigProto
()
sess_config
=
tf
.
ConfigProto
()
sess_config
.
device_count
[
'GPU'
]
=
1
sess_config
.
device_count
[
'GPU'
]
=
1
...
@@ -87,11 +90,11 @@ def main():
...
@@ -87,11 +90,11 @@ def main():
dataset_train
=
dataset_train
,
dataset_train
=
dataset_train
,
optimizer
=
tf
.
train
.
AdamOptimizer
(
1e-4
),
optimizer
=
tf
.
train
.
AdamOptimizer
(
1e-4
),
callbacks
=
[
callbacks
=
[
TrainingAccuracy
(),
TrainingAccuracy
(
batch_size
=
BATCH_SIZE
),
AccuracyValidation
(
dataset_test
,
ValidationAccuracy
(
dataset_test
,
prefix
=
'test'
,
period
=
1
),
prefix
=
'test'
,
period
=
1
),
PeriodicSaver
(
LOG_DIR
,
period
=
1
),
PeriodicSaver
(
LOG_DIR
,
period
=
1
),
SummaryWriter
(
LOG_DIR
),
SummaryWriter
(
LOG_DIR
,
histogram_regex
=
'.*/W'
),
],
],
session_config
=
sess_config
,
session_config
=
sess_config
,
inputs
=
input_vars
,
inputs
=
input_vars
,
...
...
layers/regularize.py
0 → 100644
View file @
031dd698
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
# File: regularize.py
# Author: Yuxin Wu <ppwwyyxx@gmail.com>
import
tensorflow
as
tf
import
re
__all__
=
[
'regularize_cost'
]
def
regularize_cost
(
regex
,
func
):
G
=
tf
.
get_default_graph
()
params
=
G
.
get_collection
(
tf
.
GraphKeys
.
TRAINABLE_VARIABLES
)
cost
=
0
for
p
in
params
:
name
=
p
.
name
if
re
.
search
(
regex
,
name
):
print
(
"Weight decay for {}"
.
format
(
name
))
cost
+=
func
(
p
)
return
cost
train.py
View file @
031dd698
...
@@ -58,6 +58,6 @@ def start_train(config):
...
@@ -58,6 +58,6 @@ def start_train(config):
[
train_op
,
cost_var
]
+
output_vars
,
feed_dict
=
feed
)
[
train_op
,
cost_var
]
+
output_vars
,
feed_dict
=
feed
)
cost
=
results
[
1
]
cost
=
results
[
1
]
outputs
=
results
[
2
:]
outputs
=
results
[
2
:]
callbacks
.
trigger_step
(
dp
,
outputs
,
cost
)
callbacks
.
trigger_step
(
feed
,
outputs
,
cost
)
callbacks
.
trigger_epoch
()
callbacks
.
trigger_epoch
()
utils/callback.py
View file @
031dd698
...
@@ -9,8 +9,6 @@ import numpy as np
...
@@ -9,8 +9,6 @@ import numpy as np
import
os
import
os
from
abc
import
abstractmethod
from
abc
import
abstractmethod
from
.stat
import
*
from
.utils
import
*
from
.naming
import
*
from
.naming
import
*
class
Callback
(
object
):
class
Callback
(
object
):
...
@@ -24,11 +22,11 @@ class Callback(object):
...
@@ -24,11 +22,11 @@ class Callback(object):
Called before starting iterative training
Called before starting iterative training
"""
"""
def
trigger_step
(
self
,
dp
,
outputs
,
cost
):
def
trigger_step
(
self
,
inputs
,
outputs
,
cost
):
"""
"""
Callback to be triggered after every step (every backpropagation)
Callback to be triggered after every step (every backpropagation)
Args:
Args:
dp
: the input dict fed into the graph
inputs
: the input dict fed into the graph
outputs: list of output values after running this dp
outputs: list of output values after running this dp
cost: the cost value after running this dp
cost: the cost value after running this dp
"""
"""
...
@@ -54,105 +52,6 @@ class PeriodicCallback(Callback):
...
@@ -54,105 +52,6 @@ class PeriodicCallback(Callback):
def
_trigger
(
self
):
def
_trigger
(
self
):
pass
pass
class
AccuracyValidation
(
PeriodicCallback
):
"""
Validate the accuracy for the given correct and cost variable
Use under the following setup:
correct_var: integer, number of correct samples in this batch
ds: batched dataset
"""
def
__init__
(
self
,
ds
,
prefix
,
period
=
1
,
correct_var_name
=
'correct:0'
,
cost_var_name
=
'cost:0'
):
super
(
AccuracyValidation
,
self
)
.
__init__
(
period
)
self
.
ds
=
ds
self
.
prefix
=
prefix
self
.
correct_var_name
=
correct_var_name
self
.
cost_var_name
=
cost_var_name
def
get_tensor
(
self
,
name
):
return
self
.
graph
.
get_tensor_by_name
(
name
)
def
_before_train
(
self
):
self
.
input_vars
=
self
.
graph
.
get_collection
(
INPUT_VARS_KEY
)
self
.
dropout_var
=
self
.
get_tensor
(
DROPOUT_PROB_VAR_NAME
)
self
.
correct_var
=
self
.
get_tensor
(
self
.
correct_var_name
)
self
.
cost_var
=
self
.
get_tensor
(
self
.
cost_var_name
)
self
.
writer
=
tf
.
get_collection
(
SUMMARY_WRITER_COLLECTION_KEY
)[
0
]
def
_trigger
(
self
):
cnt
=
0
correct_stat
=
Accuracy
()
cost_sum
=
0
for
dp
in
self
.
ds
.
get_data
():
feed
=
{
self
.
dropout_var
:
1.0
}
feed
.
update
(
dict
(
zip
(
self
.
input_vars
,
dp
)))
batch_size
=
dp
[
0
]
.
shape
[
0
]
# assume batched input
cnt
+=
batch_size
correct
,
cost
=
self
.
sess
.
run
(
[
self
.
correct_var
,
self
.
cost_var
],
feed_dict
=
feed
)
correct_stat
.
feed
(
correct
,
batch_size
)
# each batch might not have the same size in validation
cost_sum
+=
cost
*
batch_size
cost_avg
=
cost_sum
/
cnt
self
.
writer
.
add_summary
(
create_summary
(
'{} accuracy'
.
format
(
self
.
prefix
),
correct_stat
.
accuracy
),
self
.
epoch_num
)
self
.
writer
.
add_summary
(
create_summary
(
'{} cost'
.
format
(
self
.
prefix
),
cost_avg
),
self
.
epoch_num
)
print
"{} validation after epoch {}: acc={}, cost={}"
.
format
(
self
.
prefix
,
self
.
epoch_num
,
correct_stat
.
accuracy
,
cost_avg
)
class
TrainingAccuracy
(
Callback
):
def
__init__
(
self
,
correct_var_name
=
'correct:0'
):
"""
correct_var: number of correct sample in this batch
"""
self
.
correct_var_name
=
correct_var_name
self
.
epoch_num
=
0
def
_before_train
(
self
):
self
.
writer
=
tf
.
get_collection
(
SUMMARY_WRITER_COLLECTION_KEY
)[
0
]
output_vars
=
self
.
graph
.
get_collection
(
OUTPUT_VARS_KEY
)
for
idx
,
var
in
enumerate
(
output_vars
):
if
var
.
name
==
self
.
correct_var_name
:
self
.
correct_output_idx
=
idx
break
else
:
raise
RuntimeError
(
"'correct' variable must be in the model outputs to use TrainingAccuracy"
)
self
.
running_cost
=
StatCounter
()
self
.
running_acc
=
Accuracy
()
def
trigger_step
(
self
,
inputs
,
outputs
,
cost
):
self
.
running_cost
.
feed
(
cost
)
self
.
running_acc
.
feed
(
outputs
[
self
.
correct_output_idx
],
inputs
[
0
]
.
shape
[
0
])
# assume batch input
def
trigger_epoch
(
self
):
self
.
epoch_num
+=
1
print
(
'Training average in Epoch {}: cost={}, acc={}'
.
format
(
self
.
epoch_num
,
self
.
running_cost
.
average
,
self
.
running_acc
.
accuracy
))
self
.
writer
.
add_summary
(
create_summary
(
'training average accuracy'
,
self
.
running_acc
.
accuracy
),
self
.
epoch_num
)
self
.
writer
.
add_summary
(
create_summary
(
'training average cost'
,
self
.
running_cost
.
average
),
self
.
epoch_num
)
self
.
running_cost
.
reset
()
self
.
running_acc
.
reset
()
class
PeriodicSaver
(
PeriodicCallback
):
class
PeriodicSaver
(
PeriodicCallback
):
def
__init__
(
self
,
log_dir
,
period
=
1
):
def
__init__
(
self
,
log_dir
,
period
=
1
):
super
(
PeriodicSaver
,
self
)
.
__init__
(
period
)
super
(
PeriodicSaver
,
self
)
.
__init__
(
period
)
...
@@ -166,25 +65,35 @@ class PeriodicSaver(PeriodicCallback):
...
@@ -166,25 +65,35 @@ class PeriodicSaver(PeriodicCallback):
global_step
=
self
.
epoch_num
,
latest_filename
=
'latest'
)
global_step
=
self
.
epoch_num
,
latest_filename
=
'latest'
)
class
SummaryWriter
(
Callback
):
class
SummaryWriter
(
Callback
):
def
__init__
(
self
,
log_dir
):
def
__init__
(
self
,
log_dir
,
histogram_regex
=
None
):
self
.
log_dir
=
log_dir
self
.
log_dir
=
log_dir
self
.
epoch_num
=
0
self
.
epoch_num
=
0
self
.
hist_regex
=
histogram_regex
def
_before_train
(
self
):
def
_before_train
(
self
):
sess
=
tf
.
get_default_session
()
graph
=
tf
.
get_default_graph
()
self
.
writer
=
tf
.
train
.
SummaryWriter
(
self
.
writer
=
tf
.
train
.
SummaryWriter
(
self
.
log_dir
,
graph_def
=
sess
.
graph_def
)
self
.
log_dir
,
graph_def
=
self
.
sess
.
graph_def
)
graph
.
add_to_collection
(
SUMMARY_WRITER_COLLECTION_KEY
,
self
.
writer
)
self
.
graph
.
add_to_collection
(
SUMMARY_WRITER_COLLECTION_KEY
,
self
.
writer
)
# create some summary
if
self
.
hist_regex
is
not
None
:
import
re
params
=
self
.
graph
.
get_collection
(
tf
.
GraphKeys
.
TRAINABLE_VARIABLES
)
for
p
in
params
:
name
=
p
.
name
if
re
.
search
(
self
.
hist_regex
,
name
):
tf
.
histogram_summary
(
name
,
p
)
self
.
summary_op
=
tf
.
merge_all_summaries
()
self
.
summary_op
=
tf
.
merge_all_summaries
()
def
trigger_step
(
self
,
dp
,
outputs
,
cost
):
def
trigger_step
(
self
,
inputs
,
outputs
,
cost
):
self
.
last_dp
=
dp
self
.
last_dp
=
inputs
def
trigger_epoch
(
self
):
def
trigger_epoch
(
self
):
# check if there is any summary
# check if there is any summary
if
self
.
summary_op
is
None
:
if
self
.
summary_op
is
None
:
return
return
summary_str
=
self
.
summary_op
.
eval
(
self
.
last_dp
)
summary_str
=
self
.
summary_op
.
eval
(
self
.
last_dp
)
self
.
epoch_num
+=
1
self
.
epoch_num
+=
1
self
.
writer
.
add_summary
(
summary_str
,
self
.
epoch_num
)
self
.
writer
.
add_summary
(
summary_str
,
self
.
epoch_num
)
...
@@ -196,6 +105,8 @@ class Callbacks(Callback):
...
@@ -196,6 +105,8 @@ class Callbacks(Callback):
if
type
(
cb
)
==
SummaryWriter
:
if
type
(
cb
)
==
SummaryWriter
:
callbacks
.
insert
(
0
,
callbacks
.
pop
(
idx
))
callbacks
.
insert
(
0
,
callbacks
.
pop
(
idx
))
break
break
else
:
raise
RuntimeError
(
"callbacks must contain a SummaryWriter!"
)
self
.
callbacks
=
callbacks
self
.
callbacks
=
callbacks
...
@@ -203,9 +114,9 @@ class Callbacks(Callback):
...
@@ -203,9 +114,9 @@ class Callbacks(Callback):
for
cb
in
self
.
callbacks
:
for
cb
in
self
.
callbacks
:
cb
.
before_train
()
cb
.
before_train
()
def
trigger_step
(
self
,
dp
,
outputs
,
cost
):
def
trigger_step
(
self
,
inputs
,
outputs
,
cost
):
for
cb
in
self
.
callbacks
:
for
cb
in
self
.
callbacks
:
cb
.
trigger_step
(
dp
,
outputs
,
cost
)
cb
.
trigger_step
(
inputs
,
outputs
,
cost
)
def
trigger_epoch
(
self
):
def
trigger_epoch
(
self
):
for
cb
in
self
.
callbacks
:
for
cb
in
self
.
callbacks
:
...
...
utils/validation_callback.py
0 → 100644
View file @
031dd698
#!/usr/bin/env python2
# -*- coding: UTF-8 -*-
# File: validation_callback.py
# Author: Yuxin Wu <ppwwyyxx@gmail.com>
import
tensorflow
as
tf
from
.stat
import
*
from
.callback
import
PeriodicCallback
,
Callback
from
.naming
import
*
from
.utils
import
*
class
ValidationAccuracy
(
PeriodicCallback
):
"""
Validate the accuracy for the given correct and cost variable
Use under the following setup:
correct_var: integer, number of correct samples in this batch
ds: batched dataset
"""
def
__init__
(
self
,
ds
,
prefix
,
period
=
1
,
correct_var_name
=
'correct:0'
,
cost_var_name
=
'cost:0'
):
super
(
ValidationAccuracy
,
self
)
.
__init__
(
period
)
self
.
ds
=
ds
self
.
prefix
=
prefix
self
.
correct_var_name
=
correct_var_name
self
.
cost_var_name
=
cost_var_name
def
get_tensor
(
self
,
name
):
return
self
.
graph
.
get_tensor_by_name
(
name
)
def
_before_train
(
self
):
self
.
input_vars
=
self
.
graph
.
get_collection
(
INPUT_VARS_KEY
)
self
.
dropout_var
=
self
.
get_tensor
(
DROPOUT_PROB_VAR_NAME
)
self
.
correct_var
=
self
.
get_tensor
(
self
.
correct_var_name
)
self
.
cost_var
=
self
.
get_tensor
(
self
.
cost_var_name
)
self
.
writer
=
tf
.
get_collection
(
SUMMARY_WRITER_COLLECTION_KEY
)[
0
]
def
_trigger
(
self
):
cnt
=
0
correct_stat
=
Accuracy
()
cost_sum
=
0
for
dp
in
self
.
ds
.
get_data
():
feed
=
{
self
.
dropout_var
:
1.0
}
feed
.
update
(
dict
(
zip
(
self
.
input_vars
,
dp
)))
batch_size
=
dp
[
0
]
.
shape
[
0
]
# assume batched input
cnt
+=
batch_size
correct
,
cost
=
self
.
sess
.
run
(
[
self
.
correct_var
,
self
.
cost_var
],
feed_dict
=
feed
)
correct_stat
.
feed
(
correct
,
batch_size
)
# each batch might not have the same size in validation
cost_sum
+=
cost
*
batch_size
cost_avg
=
cost_sum
/
cnt
self
.
writer
.
add_summary
(
create_summary
(
'{} accuracy'
.
format
(
self
.
prefix
),
correct_stat
.
accuracy
),
self
.
epoch_num
)
self
.
writer
.
add_summary
(
create_summary
(
'{} cost'
.
format
(
self
.
prefix
),
cost_avg
),
self
.
epoch_num
)
print
"{} validation after epoch {}: acc={}, cost={}"
.
format
(
self
.
prefix
,
self
.
epoch_num
,
correct_stat
.
accuracy
,
cost_avg
)
class
TrainingAccuracy
(
Callback
):
"""
Record the accuracy and cost during each step of trianing.
The result is a running average, thus not directly comparable with ValidationAccuracy
"""
def
__init__
(
self
,
batch_size
,
correct_var_name
=
'correct:0'
):
"""
correct_var: number of correct sample in this batch
"""
self
.
correct_var_name
=
correct_var_name
self
.
batch_size
=
batch_size
self
.
epoch_num
=
0
def
_before_train
(
self
):
self
.
writer
=
tf
.
get_collection
(
SUMMARY_WRITER_COLLECTION_KEY
)[
0
]
output_vars
=
self
.
graph
.
get_collection
(
OUTPUT_VARS_KEY
)
for
idx
,
var
in
enumerate
(
output_vars
):
if
var
.
name
==
self
.
correct_var_name
:
self
.
correct_output_idx
=
idx
break
else
:
raise
RuntimeError
(
"'correct' variable must be in the model outputs to use TrainingAccuracy"
)
self
.
running_cost
=
StatCounter
()
self
.
running_acc
=
Accuracy
()
def
trigger_step
(
self
,
inputs
,
outputs
,
cost
):
self
.
running_cost
.
feed
(
cost
)
self
.
running_acc
.
feed
(
outputs
[
self
.
correct_output_idx
],
self
.
batch_size
)
# assume batch input
def
trigger_epoch
(
self
):
self
.
epoch_num
+=
1
print
(
'Training average in Epoch {}: cost={}, acc={}'
.
format
(
self
.
epoch_num
,
self
.
running_cost
.
average
,
self
.
running_acc
.
accuracy
))
self
.
writer
.
add_summary
(
create_summary
(
'training average accuracy'
,
self
.
running_acc
.
accuracy
),
self
.
epoch_num
)
self
.
writer
.
add_summary
(
create_summary
(
'training average cost'
,
self
.
running_cost
.
average
),
self
.
epoch_num
)
self
.
running_cost
.
reset
()
self
.
running_acc
.
reset
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment