Commit
·
e32abb5
1
Parent(s):
8056fe2
hyperparameter evolution bug fix (#566)
Browse files- train.py +12 -7
- utils/utils.py +17 -6
train.py
CHANGED
@@ -42,7 +42,7 @@ hyp = {'lr0': 0.01, # initial learning rate (SGD=1E-2, Adam=1E-3)
|
|
42 |
|
43 |
def train(hyp, opt, device, tb_writer=None):
|
44 |
print(f'Hyperparameters {hyp}')
|
45 |
-
log_dir = tb_writer.log_dir if tb_writer else 'runs/
|
46 |
wdir = str(Path(log_dir) / 'weights') + os.sep # weights directory
|
47 |
os.makedirs(wdir, exist_ok=True)
|
48 |
last = wdir + 'last.pt'
|
@@ -491,6 +491,7 @@ if __name__ == '__main__':
|
|
491 |
assert opt.local_rank == -1, 'DDP mode not implemented for --evolve'
|
492 |
opt.notest, opt.nosave = True, True # only test/save final epoch
|
493 |
# ei = [isinstance(x, (int, float)) for x in hyp.values()] # evolvable indices
|
|
|
494 |
if opt.bucket:
|
495 |
os.system('gsutil cp gs://%s/evolve.txt .' % opt.bucket) # download evolve.txt if exists
|
496 |
|
@@ -518,17 +519,21 @@ if __name__ == '__main__':
|
|
518 |
while all(v == 1): # mutate until a change occurs (prevent duplicates)
|
519 |
v = (g * (npr.random(ng) < mp) * npr.randn(ng) * npr.random() * s + 1).clip(0.3, 3.0)
|
520 |
for i, k in enumerate(hyp.keys()): # plt.hist(v.ravel(), 300)
|
521 |
-
hyp[k] = x[i + 7] * v[i] # mutate
|
522 |
|
523 |
-
#
|
524 |
for k, v in meta.items():
|
525 |
-
hyp[k] =
|
|
|
|
|
526 |
|
527 |
# Train mutation
|
528 |
results = train(hyp.copy(), opt, device)
|
529 |
|
530 |
# Write mutation results
|
531 |
-
print_mutation(hyp, results, opt.bucket)
|
532 |
|
533 |
-
|
534 |
-
|
|
|
|
|
|
42 |
|
43 |
def train(hyp, opt, device, tb_writer=None):
|
44 |
print(f'Hyperparameters {hyp}')
|
45 |
+
log_dir = tb_writer.log_dir if tb_writer else 'runs/evolve' # run directory
|
46 |
wdir = str(Path(log_dir) / 'weights') + os.sep # weights directory
|
47 |
os.makedirs(wdir, exist_ok=True)
|
48 |
last = wdir + 'last.pt'
|
|
|
491 |
assert opt.local_rank == -1, 'DDP mode not implemented for --evolve'
|
492 |
opt.notest, opt.nosave = True, True # only test/save final epoch
|
493 |
# ei = [isinstance(x, (int, float)) for x in hyp.values()] # evolvable indices
|
494 |
+
yaml_file = Path('runs/evolve/hyp_evolved.yaml') # save best result here
|
495 |
if opt.bucket:
|
496 |
os.system('gsutil cp gs://%s/evolve.txt .' % opt.bucket) # download evolve.txt if exists
|
497 |
|
|
|
519 |
while all(v == 1): # mutate until a change occurs (prevent duplicates)
|
520 |
v = (g * (npr.random(ng) < mp) * npr.randn(ng) * npr.random() * s + 1).clip(0.3, 3.0)
|
521 |
for i, k in enumerate(hyp.keys()): # plt.hist(v.ravel(), 300)
|
522 |
+
hyp[k] = float(x[i + 7] * v[i]) # mutate
|
523 |
|
524 |
+
# Constrain to limits
|
525 |
for k, v in meta.items():
|
526 |
+
hyp[k] = max(hyp[k], v[1]) # lower limit
|
527 |
+
hyp[k] = min(hyp[k], v[2]) # upper limit
|
528 |
+
hyp[k] = round(hyp[k], 5) # significant digits
|
529 |
|
530 |
# Train mutation
|
531 |
results = train(hyp.copy(), opt, device)
|
532 |
|
533 |
# Write mutation results
|
534 |
+
print_mutation(hyp.copy(), results, yaml_file, opt.bucket)
|
535 |
|
536 |
+
# Plot results
|
537 |
+
plot_evolution_results(yaml_file)
|
538 |
+
print('Hyperparameter evolution complete. Best results saved as: %s\nCommand to train a new model with these '
|
539 |
+
'hyperparameters: $ python train.py --hyp %s' % (f, f))
|
utils/utils.py
CHANGED
@@ -818,11 +818,11 @@ def kmean_anchors(path='./data/coco128.yaml', n=9, img_size=640, thr=4.0, gen=10
|
|
818 |
return print_results(k)
|
819 |
|
820 |
|
821 |
-
def print_mutation(hyp, results, bucket=''):
|
822 |
# Print mutation results to evolve.txt (for use with train.py --evolve)
|
823 |
a = '%10s' * len(hyp) % tuple(hyp.keys()) # hyperparam keys
|
824 |
b = '%10.3g' * len(hyp) % tuple(hyp.values()) # hyperparam values
|
825 |
-
c = '%10.4g' * len(results) % results # results (P, R, mAP,
|
826 |
print('\n%s\n%s\nEvolved fitness: %s\n' % (a, b, c))
|
827 |
|
828 |
if bucket:
|
@@ -831,11 +831,19 @@ def print_mutation(hyp, results, bucket=''):
|
|
831 |
with open('evolve.txt', 'a') as f: # append result
|
832 |
f.write(c + b + '\n')
|
833 |
x = np.unique(np.loadtxt('evolve.txt', ndmin=2), axis=0) # load unique rows
|
834 |
-
|
|
|
835 |
|
836 |
if bucket:
|
837 |
os.system('gsutil cp evolve.txt gs://%s' % bucket) # upload evolve.txt
|
838 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
839 |
|
840 |
def apply_classifier(x, model, img, im0):
|
841 |
# applies a second stage classifier to yolo outputs
|
@@ -1146,23 +1154,26 @@ def plot_labels(labels, save_dir=''):
|
|
1146 |
plt.close()
|
1147 |
|
1148 |
|
1149 |
-
def plot_evolution_results(
|
1150 |
# Plot hyperparameter evolution results in evolve.txt
|
|
|
|
|
1151 |
x = np.loadtxt('evolve.txt', ndmin=2)
|
1152 |
f = fitness(x)
|
1153 |
# weights = (f - f.min()) ** 2 # for weighted results
|
1154 |
-
plt.figure(figsize=(
|
1155 |
matplotlib.rc('font', **{'size': 8})
|
1156 |
for i, (k, v) in enumerate(hyp.items()):
|
1157 |
y = x[:, i + 7]
|
1158 |
# mu = (y * weights).sum() / weights.sum() # best weighted result
|
1159 |
mu = y[f.argmax()] # best single result
|
1160 |
-
plt.subplot(4,
|
1161 |
plt.plot(mu, f.max(), 'o', markersize=10)
|
1162 |
plt.plot(y, f, '.')
|
1163 |
plt.title('%s = %.3g' % (k, mu), fontdict={'size': 9}) # limit to 40 characters
|
1164 |
print('%15s: %.3g' % (k, mu))
|
1165 |
plt.savefig('evolve.png', dpi=200)
|
|
|
1166 |
|
1167 |
|
1168 |
def plot_results_overlay(start=0, stop=0): # from utils.utils import *; plot_results_overlay()
|
|
|
818 |
return print_results(k)
|
819 |
|
820 |
|
821 |
+
def print_mutation(hyp, results, yaml_file='hyp_evolved.yaml', bucket=''):
|
822 |
# Print mutation results to evolve.txt (for use with train.py --evolve)
|
823 |
a = '%10s' * len(hyp) % tuple(hyp.keys()) # hyperparam keys
|
824 |
b = '%10.3g' * len(hyp) % tuple(hyp.values()) # hyperparam values
|
825 |
+
c = '%10.4g' * len(results) % results # results (P, R, mAP@0.5, [email protected]:0.95, val_losses x 3)
|
826 |
print('\n%s\n%s\nEvolved fitness: %s\n' % (a, b, c))
|
827 |
|
828 |
if bucket:
|
|
|
831 |
with open('evolve.txt', 'a') as f: # append result
|
832 |
f.write(c + b + '\n')
|
833 |
x = np.unique(np.loadtxt('evolve.txt', ndmin=2), axis=0) # load unique rows
|
834 |
+
x = x[np.argsort(-fitness(x))] # sort
|
835 |
+
np.savetxt('evolve.txt', x, '%10.3g') # save sort by fitness
|
836 |
|
837 |
if bucket:
|
838 |
os.system('gsutil cp evolve.txt gs://%s' % bucket) # upload evolve.txt
|
839 |
|
840 |
+
# Save yaml
|
841 |
+
for i, k in enumerate(hyp.keys()):
|
842 |
+
hyp[k] = float(x[0, i + 7])
|
843 |
+
with open(yaml_file, 'w') as f:
|
844 |
+
f.write('# Hyperparameter Evolution Results\n# Generations: %g\n# Metrics: ' % len(x) + c + '\n\n')
|
845 |
+
yaml.dump(hyp, f, sort_keys=False)
|
846 |
+
|
847 |
|
848 |
def apply_classifier(x, model, img, im0):
|
849 |
# applies a second stage classifier to yolo outputs
|
|
|
1154 |
plt.close()
|
1155 |
|
1156 |
|
1157 |
+
def plot_evolution_results(yaml_file='hyp_evolved.yaml'): # from utils.utils import *; plot_evolution_results()
|
1158 |
# Plot hyperparameter evolution results in evolve.txt
|
1159 |
+
with open(yaml_file) as f:
|
1160 |
+
hyp = yaml.load(f, Loader=yaml.FullLoader)
|
1161 |
x = np.loadtxt('evolve.txt', ndmin=2)
|
1162 |
f = fitness(x)
|
1163 |
# weights = (f - f.min()) ** 2 # for weighted results
|
1164 |
+
plt.figure(figsize=(14, 10), tight_layout=True)
|
1165 |
matplotlib.rc('font', **{'size': 8})
|
1166 |
for i, (k, v) in enumerate(hyp.items()):
|
1167 |
y = x[:, i + 7]
|
1168 |
# mu = (y * weights).sum() / weights.sum() # best weighted result
|
1169 |
mu = y[f.argmax()] # best single result
|
1170 |
+
plt.subplot(4, 6, i + 1)
|
1171 |
plt.plot(mu, f.max(), 'o', markersize=10)
|
1172 |
plt.plot(y, f, '.')
|
1173 |
plt.title('%s = %.3g' % (k, mu), fontdict={'size': 9}) # limit to 40 characters
|
1174 |
print('%15s: %.3g' % (k, mu))
|
1175 |
plt.savefig('evolve.png', dpi=200)
|
1176 |
+
print('\nPlot saved as evolve.png')
|
1177 |
|
1178 |
|
1179 |
def plot_results_overlay(start=0, stop=0): # from utils.utils import *; plot_results_overlay()
|