| @@ -0,0 +1,12 @@ | ||
| YOLO LICENSE | ||
| Version 2, July 29 2016 | ||
|
|
||
| THIS SOFTWARE LICENSE IS PROVIDED "ALL CAPS" SO THAT YOU KNOW IT IS SUPER | ||
| SERIOUS AND YOU DON'T MESS AROUND WITH COPYRIGHT LAW BECAUSE YOU WILL GET IN | ||
| TROUBLE HERE ARE SOME OTHER BUZZWORDS COMMONLY IN THESE THINGS WARRANTIES | ||
| LIABILITY CONTRACT TORT LIABLE CLAIMS RESTRICTION MERCHANTABILITY. NOW HERE'S | ||
| THE REAL LICENSE: | ||
|
|
||
| 0. Darknet is public domain. | ||
| 1. Do whatever you want with it. | ||
| 2. Stop emailing me about it! |
| @@ -0,0 +1,82 @@ | ||
| GPU=1 | ||
| CUDNN=1 | ||
| OPENCV=1 | ||
| DEBUG=0 | ||
|
|
||
| ARCH= -gencode arch=compute_20,code=[sm_20,sm_21] \ | ||
| -gencode arch=compute_30,code=sm_30 \ | ||
| -gencode arch=compute_35,code=sm_35 \ | ||
| -gencode arch=compute_50,code=[sm_50,compute_50] \ | ||
| -gencode arch=compute_52,code=[sm_52,compute_52] | ||
|
|
||
| # This is what I use, uncomment if you know your arch and want to specify | ||
| #ARCH= -gencode arch=compute_50,code=compute_50 | ||
|
|
||
| VPATH=./src/ | ||
| EXEC=darknet | ||
| OBJDIR=./obj/ | ||
|
|
||
| CC=gcc | ||
| NVCC=nvcc | ||
| OPTS=-Ofast | ||
| LDFLAGS= -lm -pthread | ||
| COMMON= | ||
| CFLAGS=-Wall -Wfatal-errors | ||
|
|
||
| ifeq ($(DEBUG), 1) | ||
| OPTS=-O1 -g | ||
| endif | ||
|
|
||
| CFLAGS+=$(OPTS) | ||
|
|
||
| ifeq ($(OPENCV), 1) | ||
| COMMON+= -DOPENCV | ||
| CFLAGS+= -DOPENCV | ||
| LDFLAGS+= `pkg-config --libs opencv` | ||
| COMMON+= `pkg-config --cflags opencv` | ||
| endif | ||
|
|
||
| ifeq ($(GPU), 1) | ||
| COMMON+= -DGPU -I/usr/local/cuda/include/ | ||
| CFLAGS+= -DGPU | ||
| LDFLAGS+= -L/usr/local/cuda/lib64 -lcuda -lcudart -lcublas -lcurand -lm | ||
| endif | ||
|
|
||
| ifeq ($(CUDNN), 1) | ||
| COMMON+= -DCUDNN | ||
| CFLAGS+= -DCUDNN | ||
| LDFLAGS+= -lcudnn | ||
| endif | ||
|
|
||
| OBJ=gemm.o utils.o cuda.o deconvolutional_layer.o convolutional_layer.o list.o image.o activations.o im2col.o col2im.o blas.o crop_layer.o dropout_layer.o maxpool_layer.o softmax_layer.o data.o matrix.o network.o connected_layer.o cost_layer.o parser.o option_list.o darknet.o detection_layer.o captcha.o route_layer.o writing.o box.o nightmare.o normalization_layer.o avgpool_layer.o coco.o dice.o yolo.o detector.o layer.o compare.o regressor.o classifier.o local_layer.o swag.o shortcut_layer.o activation_layer.o rnn_layer.o gru_layer.o rnn.o rnn_vid.o crnn_layer.o demo.o tag.o cifar.o go.o batchnorm_layer.o art.o region_layer.o reorg_layer.o lsd.o super.o voxel.o tree.o | ||
| ifeq ($(GPU), 1) | ||
| LDFLAGS+= -lstdc++ | ||
| OBJ+=convolutional_kernels.o deconvolutional_kernels.o activation_kernels.o im2col_kernels.o col2im_kernels.o blas_kernels.o crop_layer_kernels.o dropout_layer_kernels.o maxpool_layer_kernels.o network_kernels.o avgpool_layer_kernels.o | ||
| endif | ||
|
|
||
| OBJS = $(addprefix $(OBJDIR), $(OBJ)) | ||
| DEPS = $(wildcard src/*.h) Makefile | ||
|
|
||
| all: obj backup results $(EXEC) | ||
|
|
||
| $(EXEC): $(OBJS) | ||
| $(CC) $(COMMON) $(CFLAGS) $^ -o $@ $(LDFLAGS) | ||
|
|
||
| $(OBJDIR)%.o: %.c $(DEPS) | ||
| $(CC) $(COMMON) $(CFLAGS) -c $< -o $@ | ||
|
|
||
| $(OBJDIR)%.o: %.cu $(DEPS) | ||
| $(NVCC) $(ARCH) $(COMMON) --compiler-options "$(CFLAGS)" -c $< -o $@ | ||
|
|
||
| obj: | ||
| mkdir -p obj | ||
| backup: | ||
| mkdir -p backup | ||
| results: | ||
| mkdir -p results | ||
|
|
||
| .PHONY: clean | ||
|
|
||
| clean: | ||
| rm -rf $(OBJS) $(EXEC) | ||
|
|
| @@ -0,0 +1,82 @@ | ||
| GPU=1 | ||
| CUDNN=1 | ||
| OPENCV=1 | ||
| DEBUG=0 | ||
|
|
||
| ARCH= -gencode arch=compute_20,code=[sm_20,sm_21] \ | ||
| -gencode arch=compute_30,code=sm_30 \ | ||
| -gencode arch=compute_35,code=sm_35 \ | ||
| -gencode arch=compute_50,code=[sm_50,compute_50] \ | ||
| -gencode arch=compute_52,code=[sm_52,compute_52] | ||
|
|
||
| # This is what I use, uncomment if you know your arch and want to specify | ||
| #ARCH= -gencode arch=compute_50,code=compute_50 | ||
|
|
||
| VPATH=./src/ | ||
| EXEC=darknet | ||
| OBJDIR=./obj/ | ||
|
|
||
| CC=gcc | ||
| NVCC=nvcc | ||
| OPTS=-Ofast | ||
| LDFLAGS= -lm -pthread | ||
| COMMON= | ||
| CFLAGS=-Wall -Wfatal-errors | ||
|
|
||
| ifeq ($(DEBUG), 1) | ||
| OPTS=-O0 -g | ||
| endif | ||
|
|
||
| CFLAGS+=$(OPTS) | ||
|
|
||
| ifeq ($(OPENCV), 1) | ||
| COMMON+= -DOPENCV | ||
| CFLAGS+= -DOPENCV | ||
| LDFLAGS+= `pkg-config --libs opencv` | ||
| COMMON+= `pkg-config --cflags opencv` | ||
| endif | ||
|
|
||
| ifeq ($(GPU), 1) | ||
| COMMON+= -DGPU -I/usr/local/cuda/include/ | ||
| CFLAGS+= -DGPU | ||
| LDFLAGS+= -L/usr/local/cuda/lib64 -lcuda -lcudart -lcublas -lcurand | ||
| endif | ||
|
|
||
| ifeq ($(CUDNN), 1) | ||
| COMMON+= -DCUDNN | ||
| CFLAGS+= -DCUDNN | ||
| LDFLAGS+= -lcudnn | ||
| endif | ||
|
|
||
| OBJ=gemm.o utils.o cuda.o deconvolutional_layer.o convolutional_layer.o list.o image.o activations.o im2col.o col2im.o blas.o crop_layer.o dropout_layer.o maxpool_layer.o softmax_layer.o data.o matrix.o network.o connected_layer.o cost_layer.o parser.o option_list.o darknet.o detection_layer.o captcha.o route_layer.o writing.o box.o nightmare.o normalization_layer.o avgpool_layer.o coco.o dice.o yolo.o detector.o layer.o compare.o regressor.o classifier.o local_layer.o swag.o shortcut_layer.o activation_layer.o rnn_layer.o gru_layer.o rnn.o rnn_vid.o crnn_layer.o demo.o tag.o cifar.o go.o batchnorm_layer.o art.o region_layer.o reorg_layer.o lsd.o super.o voxel.o tree.o | ||
| ifeq ($(GPU), 1) | ||
| LDFLAGS+= -lstdc++ | ||
| OBJ+=convolutional_kernels.o deconvolutional_kernels.o activation_kernels.o im2col_kernels.o col2im_kernels.o blas_kernels.o crop_layer_kernels.o dropout_layer_kernels.o maxpool_layer_kernels.o network_kernels.o avgpool_layer_kernels.o | ||
| endif | ||
|
|
||
| OBJS = $(addprefix $(OBJDIR), $(OBJ)) | ||
| DEPS = $(wildcard src/*.h) Makefile | ||
|
|
||
| all: obj backup results $(EXEC) | ||
|
|
||
| $(EXEC): $(OBJS) | ||
| $(CC) $(COMMON) $(CFLAGS) $^ -o $@ $(LDFLAGS) | ||
|
|
||
| $(OBJDIR)%.o: %.c $(DEPS) | ||
| $(CC) $(COMMON) $(CFLAGS) -c $< -o $@ | ||
|
|
||
| $(OBJDIR)%.o: %.cu $(DEPS) | ||
| $(NVCC) $(ARCH) $(COMMON) --compiler-options "$(CFLAGS)" -c $< -o $@ | ||
|
|
||
| obj: | ||
| mkdir -p obj | ||
| backup: | ||
| mkdir -p backup | ||
| results: | ||
| mkdir -p results | ||
|
|
||
| .PHONY: clean | ||
|
|
||
| clean: | ||
| rm -rf $(OBJS) $(EXEC) | ||
|
|
| @@ -0,0 +1,8 @@ | ||
|  | ||
|
|
||
| #Darknet# | ||
| Darknet is an open source neural network framework written in C and CUDA. It is fast, easy to install, and supports CPU and GPU computation. | ||
|
|
||
| For more information see the [Darknet project website](http://pjreddie.com/darknet). | ||
|
|
||
| For questions or issues please use the [Google Group](https://groups.google.com/forum/#!forum/darknet). |
| @@ -0,0 +1 @@ | ||
| /home/dean/data/VOCdevkit/ |
| @@ -0,0 +1,7 @@ | ||
| data/dog/jpg | ||
| cfg/tiny-yolo-voc.test.cfg | ||
| classes= 2 | ||
| /home/dean/data/stop-yield-data/stopsign_00099.jpg | ||
| /home/dean/data/stop-yield-data/stopsign_00001.jpg | ||
| /home/dean/data/stop-yield-data/teat/stopsign_00001.jpg | ||
| /home/data/stop-yield-data/images/yieldsign/yield_001.JPEG |
| @@ -0,0 +1 @@ | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data |
| @@ -0,0 +1,56 @@ | ||
| import xml.etree.ElementTree as ET | ||
| import pickle | ||
| import os | ||
| from os import listdir, getcwd | ||
| from os.path import join | ||
|
|
||
| sets=[('train'), ('val'), ('test')] | ||
|
|
||
| classes = ["tote", "ball"] | ||
|
|
||
| devkit='/home/dean/data/frc-robotics/ball_tote_devkit/data' | ||
|
|
||
| def convert(size, box): | ||
| dw = 1./(size[0]) | ||
| dh = 1./(size[1]) | ||
| x = (box[0] + box[1])/2.0 - 1 | ||
| y = (box[2] + box[3])/2.0 - 1 | ||
| w = box[1] - box[0] | ||
| h = box[3] - box[2] | ||
| x = x*dw | ||
| w = w*dw | ||
| y = y*dh | ||
| h = h*dh | ||
| return (x,y,w,h) | ||
|
|
||
| def convert_annotation(image_id): | ||
| in_file = open('%s/Annotations/%s.xml'%(devkit,image_id)) | ||
| out_file = open('%s/labels/%s.txt'%(devkit,image_id), 'w') | ||
| tree=ET.parse(in_file) | ||
| root = tree.getroot() | ||
| size = root.find('size') | ||
| w = int(size.find('width').text) | ||
| h = int(size.find('height').text) | ||
|
|
||
| for obj in root.iter('object'): | ||
| difficult = obj.find('difficult').text | ||
| cls = obj.find('name').text | ||
| if cls not in classes or int(difficult)==1: | ||
| continue | ||
| cls_id = classes.index(cls) | ||
| xmlbox = obj.find('bndbox') | ||
| b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text)) | ||
| bb = convert((w,h), b) | ||
| out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n') | ||
|
|
||
| wd = getcwd() | ||
|
|
||
| if not os.path.exists('%s/labels'%(devkit)): | ||
| os.makedirs('%s/labels'%(devkit)) | ||
| image_ids = open('%s/ImageSets/train.txt'%(devkit)).read().strip().split() | ||
| list_file = open('balltote_train.txt', 'w') | ||
| for image_id in image_ids: | ||
| list_file.write('%s/Images/%s.jpg\n'%(devkit, image_id)) | ||
| convert_annotation(image_id) | ||
| list_file.close() | ||
|
|
| @@ -0,0 +1,37 @@ | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0163.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0164.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0165.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0166.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0167.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0168.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0169.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0170.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0171.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0172.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0173.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0174.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0188.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0192.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0200.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0201.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0205.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0221.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0222.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0223.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0229.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0230.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0243.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0244.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0245.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0246.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0247.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0248.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0249.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0250.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0251.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0252.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0253.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0254.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0255.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0256.jpg | ||
| /home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0257.jpg |
| @@ -0,0 +1,14 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| rm -f /tmp/sim-camera/* | ||
| WEIGHTS=weights/tiny-yolo-balltote_2000.weights | ||
|
|
||
| CFG=cfg/tiny-yolo-2class.cfg | ||
|
|
||
| FILE="http://192.168.1.107:5002/?action=stream?dummy=param.mjpg" | ||
| #FILE="videos/balltote3.mp4" | ||
|
|
||
|
|
||
| #darknet detector demo cfg/balltote.data ${CFG} ${WEIGHTS} ${FILE} -thresh 0.2 -w 320 -h 240 -fps 20 -clear | ||
| darknet detector demo cfg/balltote.data ${CFG} ${WEIGHTS} ${FILE} -thresh 0.2 | ||
|
|
| @@ -0,0 +1,9 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| WEIGHTS=weights/yolo-tiny-2class.1000.weights | ||
| #WEIGHTS=output/tiny-yolo-signs_900.weights | ||
| CFG=cfg/tiny-yolo-signs.cfg | ||
| VIDEO=videos/train.list | ||
|
|
||
| darknet detector demo data/signs.data ${CFG} ${WEIGHTS} videos/yieldsigns2.mp4 | ||
|
|
| @@ -0,0 +1,7 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| WEIGHTS=weights/yolo-2class.3000.weights | ||
| CFG=cfg/yolo-2class.cfg | ||
|
|
||
| darknet detector demo data/signs.data ${CFG} ${WEIGHTS} videos/yieldsigns2.mp4 | ||
|
|
| @@ -0,0 +1,20 @@ | ||
| mkdir -p images | ||
| mkdir -p images/orig | ||
| mkdir -p images/train | ||
| mkdir -p images/val | ||
|
|
||
| ffmpeg -i Face1.mp4 images/orig/face1_%6d.jpg | ||
| ffmpeg -i Face2.mp4 images/orig/face2_%6d.jpg | ||
| ffmpeg -i Face3.mp4 images/orig/face3_%6d.jpg | ||
| ffmpeg -i Face4.mp4 images/orig/face4_%6d.jpg | ||
| ffmpeg -i Face5.mp4 images/orig/face5_%6d.jpg | ||
| ffmpeg -i Face6.mp4 images/orig/face6_%6d.jpg | ||
|
|
||
| mogrify -resize 100x100^ -gravity center -crop 100x100+0+0 +repage images/orig/* | ||
|
|
||
| ls images/orig/* | shuf | head -n 1000 | xargs mv -t images/val | ||
| mv images/orig/* images/train | ||
|
|
||
| find `pwd`/images/train > dice.train.list -name \*.jpg | ||
| find `pwd`/images/val > dice.val.list -name \*.jpg | ||
|
|
| @@ -0,0 +1,5 @@ | ||
| #!/bin/bash | ||
| # Usage: | ||
| # wget http://pjreddie.com/media/files/peek.weights | ||
| # scripts/gen_tactic.sh < data/goal.txt | ||
| ./darknet rnn generatetactic cfg/gru.cfg peek.weights 2>/dev/null |
| @@ -0,0 +1,31 @@ | ||
| #!/bin/bash | ||
|
|
||
| # Clone COCO API | ||
| git clone https://github.com/pdollar/coco | ||
| cd coco | ||
|
|
||
| mkdir images | ||
| cd images | ||
|
|
||
| # Download Images | ||
| wget -c https://pjreddie.com/media/files/train2014.zip | ||
| wget -c https://pjreddie.com/media/files/val2014.zip | ||
|
|
||
| # Unzip | ||
| unzip -q train2014.zip | ||
| unzip -q val2014.zip | ||
|
|
||
| cd .. | ||
|
|
||
| # Download COCO Metadata | ||
| wget -c https://pjreddie.com/media/files/instances_train-val2014.zip | ||
| wget -c https://pjreddie.com/media/files/coco/5k.part | ||
| wget -c https://pjreddie.com/media/files/coco/trainvalno5k.part | ||
| wget -c https://pjreddie.com/media/files/coco/labels.tgz | ||
| tar xzf labels.tgz | ||
| unzip -q instances_train-val2014.zip | ||
|
|
||
| # Set Up Image Lists | ||
| paste <(awk "{print \"$PWD\"}" <5k.part) 5k.part | tr -d '\t' > 5k.txt | ||
| paste <(awk "{print \"$PWD\"}" <trainvalno5k.part) trainvalno5k.part | tr -d '\t' > trainvalno5k.txt | ||
|
|
| @@ -0,0 +1,15 @@ | ||
| #!/bin/bash | ||
|
|
||
| mkdir -p labelled | ||
| wd=`pwd` | ||
|
|
||
| for f in val/*.xml; | ||
| do | ||
| label=`grep -m1 "<name>" $f | grep -oP '<name>\K[^<]*'` | ||
| im=`echo $f | sed 's/val/imgs/; s/xml/JPEG/'` | ||
| out=`echo $im | sed 's/JPEG/'${label}'.JPEG/; s/imgs/labelled/'` | ||
| ln -s ${wd}/$im ${wd}/$out | ||
| done | ||
|
|
||
| find ${wd}/labelled -name \*.JPEG > inet.val.list | ||
|
|
| @@ -0,0 +1,3 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| plot_log.py ../logs/balltote_tiny_train.txt --all |
| @@ -0,0 +1,199 @@ | ||
| #!/usr/bin/env python | ||
|
|
||
| """ | ||
| Parse training log | ||
| Evolved from parse_log.sh | ||
| """ | ||
|
|
||
| import os | ||
| import re | ||
| import argparse | ||
| import csv | ||
| from collections import OrderedDict | ||
| import matplotlib.pyplot as plt | ||
| import matplotlib.cm as cm | ||
| import numpy as np | ||
|
|
||
|
|
||
| """ | ||
| sample output | ||
| Loaded: 2.528628 seconds | ||
| Region Avg IOU: 0.227440, Class: 0.079891, Obj: 0.553766, No Obj: 0.518204, Avg Recall: 0.055556, count: 18 | ||
| Region Avg IOU: 0.106427, Class: 0.056761, Obj: 0.625433, No Obj: 0.514253, Avg Recall: 0.000000, count: 14 | ||
| Region Avg IOU: 0.165932, Class: 0.028226, Obj: 0.376734, No Obj: 0.517029, Avg Recall: 0.038462, count: 26 | ||
| Region Avg IOU: 0.140938, Class: 0.090396, Obj: 0.422523, No Obj: 0.518810, Avg Recall: 0.034483, count: 29 | ||
| Region Avg IOU: 0.193469, Class: 0.061432, Obj: 0.645408, No Obj: 0.514188, Avg Recall: 0.055556, count: 18 | ||
| Region Avg IOU: 0.354011, Class: 0.027257, Obj: 0.447333, No Obj: 0.514265, Avg Recall: 0.333333, count: 9 | ||
| Region Avg IOU: 0.164411, Class: 0.026563, Obj: 0.517987, No Obj: 0.516759, Avg Recall: 0.000000, count: 13 | ||
| Region Avg IOU: 0.115462, Class: 0.021012, Obj: 0.316927, No Obj: 0.515158, Avg Recall: 0.000000, count: 9 | ||
| 1: 292.968048, 292.968048 avg, 0.000100 rate, 4.789057 seconds, 64 images | ||
| """ | ||
|
|
||
| def parse_log(path_to_log): | ||
| """Parse log file | ||
| Returns (train_dict_list, test_dict_list) | ||
| train_dict_list and test_dict_list are lists of dicts that define the table | ||
| rows | ||
| """ | ||
| rgnstr= 'Region Avg IOU: ([\.\deE+-]+), Class: ([\.\deE+-]+), Obj: ([\.\deE+-]+), No Obj: ([\.\deE+-]+), Avg Recall: ([\.\deE+-]+), count: (\d+)' | ||
| itrstr='(\d+): ([\.\deE+-]+), ([\.\deE+-]+) avg, ([\.\deE+-]+) rate, ([\.\deE+-]+) seconds, (\d+) images' | ||
| regex_region = re.compile(rgnstr) | ||
| regex_iteration = re.compile(itrstr) | ||
|
|
||
| # Pick out lines of interest | ||
| iteration = 0 | ||
| train_dict_list = [] | ||
| train_row = None | ||
| IOU=0.0 | ||
| Class=0.0 | ||
| Obj=0.0 | ||
| NoObj=0.0 | ||
| Recall=0.0 | ||
| rcnt=0 | ||
|
|
||
| with open(path_to_log) as f: | ||
| for line in f: | ||
| region_match = regex_region.search(line) | ||
| if region_match: | ||
| IOU += float(region_match.group(1)) | ||
| Class += float(region_match.group(2)) | ||
| Obj += float(region_match.group(3)) | ||
| NoObj += float(region_match.group(4)) | ||
| Recall += float(region_match.group(5)) | ||
| rcnt += 1 | ||
| region_match = regex_region.search(line) | ||
|
|
||
| iteration=0 | ||
| loss = 0.0 | ||
| aveloss = 0.0 | ||
| rate = 0.0 | ||
| time=0.0 | ||
| images = 0 | ||
|
|
||
| iteration_match = regex_iteration.search(line) | ||
| if iteration_match: | ||
| if rcnt>0: | ||
| IOU /= rcnt | ||
| Class /= rcnt | ||
| Obj /= rcnt | ||
| NoObj /= rcnt | ||
| Recall /= rcnt | ||
|
|
||
|
|
||
| iteration = float(iteration_match.group(1)) | ||
| loss = float(iteration_match.group(2)) | ||
| aveloss = float(iteration_match.group(3)) | ||
| rate = float(iteration_match.group(4)) | ||
| time = float(iteration_match.group(5)) | ||
| images = float(iteration_match.group(6)) | ||
|
|
||
| row = OrderedDict([ | ||
| ('iter', iteration), | ||
| ('loss', loss), | ||
| ('aveloss', aveloss), | ||
| ('rate', rate), | ||
| ('images', images), | ||
| ('IOU', IOU), | ||
| ('class', Class), | ||
| ('obj', Obj), | ||
| ('noobj', NoObj), | ||
| ('recall', Recall) | ||
| ]) | ||
| IOU=0.0 | ||
| Class=0.0 | ||
| Obj=0.0 | ||
| NoObj=0.0 | ||
| Recall=0.0 | ||
| rcnt=0 | ||
| train_dict_list.append(row) | ||
|
|
||
| return train_dict_list | ||
|
|
||
| def plot(itrs,loss,IOU,cls,obj,nobj,recall,plot_all): | ||
|
|
||
| fig, ax1 = plt.subplots() | ||
| ax1.plot(itrs,loss,color='k') | ||
| ax1.set_xlabel('Iteration') | ||
| #plt.figure(figsize=(10, 8)) | ||
| ax1.set_ylabel('Loss', color='k') | ||
| if plot_all: | ||
| nplots=5 | ||
| else: | ||
| nplots=3 | ||
| colors = iter(cm.rainbow(np.linspace(0, 1, nplots))) | ||
| ax2 = ax1.twinx() | ||
| ax2.set_ylim([0,1.0]) | ||
| ax2.plot(itrs, IOU,color=next(colors)) | ||
| ax2.plot(itrs, cls,color=next(colors)) | ||
|
|
||
| if plot_all: | ||
| ax2.plot(itrs, obj,color=next(colors)) | ||
| ax2.plot(itrs, nobj,color=next(colors)) | ||
| ax2.plot(itrs, recall,color=next(colors)) | ||
|
|
||
| plt.title('Training Plot', fontsize=20) | ||
| ax1.grid(True) | ||
|
|
||
| ax1.legend(['loss'], loc='upper left') | ||
| if plot_all: | ||
| ax2.legend(['IOU', 'class' ,'obj', 'nobj', 'recall'], loc='upper right') | ||
| else: | ||
| ax2.legend(['IOU', 'class'], loc='upper right') | ||
|
|
||
|
|
||
| plt.show() | ||
|
|
||
| def plot_lists(dict_lists,plot_all): | ||
| Loss=[] | ||
| Itrs=[] | ||
| IOU=[] | ||
| Class=[] | ||
| Recall=[] | ||
| Obj=[] | ||
| NoObj=[] | ||
|
|
||
| for index in range(len(dict_lists)): | ||
| line = dict_lists[index] | ||
| # print(line) | ||
| Itrs.append(line['iter']) | ||
| Loss.append(line['aveloss']) | ||
| IOU.append(line['IOU']) | ||
| Class.append(line['class']) | ||
| Recall.append(line['recall']) | ||
| Obj.append(line['obj']) | ||
| NoObj.append(line['noobj']) | ||
|
|
||
| plot(Itrs,Loss,IOU,Class,Obj,NoObj,Recall,plot_all) | ||
|
|
||
| def parse_args(): | ||
| description = ('Plot/Parse a faster-rcnn training log') | ||
| parser = argparse.ArgumentParser(description=description) | ||
|
|
||
| parser.add_argument('logfile_path', | ||
| help='Path to log file (required)') | ||
|
|
||
| parser.add_argument('--all', '-all', action='store_true') | ||
|
|
||
|
|
||
| args = parser.parse_args() | ||
| return args | ||
|
|
||
| Debug=False | ||
| if Debug == True: | ||
| logfile_path='/home/dean/AI/darknet/logs/voc_train.txt' | ||
| dict_list=[] | ||
| dict_list = parse_log(logfile_path) | ||
| plot_lists(dict_list,True) | ||
|
|
||
| def main(): | ||
| args = parse_args() | ||
| logfile_path=args.logfile_path | ||
| dict_list=[] | ||
| dict_list = parse_log(logfile_path) | ||
|
|
||
| plot_lists(dict_list,args.all) | ||
|
|
||
| if __name__ == '__main__': | ||
| main() |
| @@ -0,0 +1,10 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| IMAGE=/home/dean/data/frc-robotics/ball_tote_devkit/data/JPEGImages/0222.jpg | ||
| IMAGE="/home/dean/data/frc-robotics/ball-tote/ball/default_ShooterCamera(1)-0246.jpg" | ||
|
|
||
| WEIGHTS=weights/tiny-yolo-balltote_2000.weights | ||
|
|
||
| CFG=cfg/tiny-yolo-2class.cfg | ||
|
|
||
| darknet detector test cfg/balltote.data ${CFG} ${WEIGHTS} ${IMAGE} |
| @@ -0,0 +1,10 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| IMAGE=/home/dean/data/stop-yield-data/test/stopsign_00001.jpg | ||
| #IMAGE=/home/dean/data/stop-yield-data/images/stopsign/003.jpg | ||
|
|
||
| WEIGHTS=weights/yolo-tiny-2class.1000.weights | ||
|
|
||
| CFG=cfg/tiny-yolo-signs.cfg | ||
|
|
||
| darknet detector test data/signs.data ${CFG} ${WEIGHTS} ${IMAGE} |
| @@ -0,0 +1,13 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| #IMAGE=data/dog.jpg | ||
| #IMAGE=/home/dean/data/voc-data/small/train/images/2007_000256.jpg | ||
| IMAGE=/home/dean/data/stop-yield-data/test/stopsign_00001.jpg | ||
| #IMAGE=/home/dean/data/stop-yield-data/images/stopsign/003.jpg | ||
|
|
||
| WEIGHTS=weights/yolo-2class.3000.weights | ||
| #WEIGHTS=weights/yolo-2class-1000-dn448.weights | ||
|
|
||
| CFG=cfg/yolo-2class.cfg | ||
|
|
||
| darknet detector test data/signs.data ${CFG} ${WEIGHTS} ${IMAGE} -thresh 0.1 |
| @@ -0,0 +1,12 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| #IMAGE=data/dog.jpg | ||
| #IMAGE=/home/dean/data/voc-data/small/train/images/2007_000256.jpg | ||
| IMAGE=/home/dean/AI/darknet/VOCdevkit/VOC2007/JPEGImages/000230.jpg | ||
|
|
||
| #WEIGHTS=weights/yolo-voc-trained-1000.weights | ||
| WEIGHTS=output/yolo-voc.backup | ||
|
|
||
| CFG=cfg/yolo-voc.2.0.test.cfg | ||
|
|
||
| darknet detector test cfg/voc.data ${CFG} ${WEIGHTS} ${IMAGE} -thresh 0.25 |
| @@ -0,0 +1,13 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| LOG=logs/balltote_tiny_train.txt | ||
| exec &> >(tee "$LOG") | ||
| echo Logging output to "$LOG" | ||
|
|
||
| WEIGHTS=weights/yolo-tiny-2class.1000.weights | ||
| CFG=cfg/tiny-yolo-2class.cfg | ||
|
|
||
| #darknet detector train cfg/voc.data cfg/yolo-voc.2.0.train.cfg darknet19_448.conv.23 | ||
| #darknet detector train cfg/balltote.data cfg/tiny-yolo-balltote-train.cfg output/tiny-yolo-balltote-train_100-last.weights | ||
| time darknet detector train cfg/balltote.data ${CFG} ${WEIGHTS} | ||
|
|
| @@ -0,0 +1,9 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| LOG=logs/signs_tiny_train.txt | ||
| exec &> >(tee "$LOG") | ||
| echo Logging output to "$LOG" | ||
|
|
||
| WEIGHTS=weights/tiny-yolo-12.weights | ||
|
|
||
| time darknet detector train data/signs.data cfg/tiny-yolo-signs.cfg ${WEIGHTS} |
| @@ -0,0 +1,11 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| LOG=logs/signs_train.txt | ||
| exec &> >(tee "$LOG") | ||
| echo Logging output to "$LOG" | ||
|
|
||
| WEIGHTS=weights/darknet19_448.conv.23 | ||
|
|
||
| #darknet yolo train cfg/yolo_2class_box11.cfg ${WEIGHTS} | ||
| darknet detector train data/signs.data cfg/yolo-2class.cfg ${WEIGHTS} | ||
|
|
| @@ -0,0 +1,8 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| LOG=logs/voc_tiny_train.txt | ||
| exec &> >(tee "$LOG") | ||
| echo Logging output to "$LOG" | ||
|
|
||
| #darknet detector train cfg/voc.data cfg/yolo-voc.2.0.train.cfg darknet19_448.conv.23 | ||
| darknet detector train cfg/voc.data cfg/tiny-yolo-voc.cfg weights/tiny-yolo-voc.weights |
| @@ -0,0 +1,9 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| LOG=logs/voc_train2.txt | ||
| exec &> >(tee "$LOG") | ||
| echo Logging output to "$LOG" | ||
|
|
||
| #darknet detector train cfg/voc.data cfg/yolo-voc.2.0.train.cfg darknet19_448.conv.23 | ||
| #darknet detector train cfg/voc.data cfg/yolo-voc.2.0.train.cfg weights/yolo-voc-trained-1000.weights | ||
| darknet detector train cfg/voc.data cfg/yolo-voc.2.0.train.cfg weights/yolo-voc_final.weights |
| @@ -0,0 +1,9 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| # note: had to chage hard-coded path to 2007_test.txt in yolo.c | ||
| TEST=/home/dean/AI/darknet/balltote_train.txt | ||
| CFG=cfg/tiny-yolo-balltote-train.cfg | ||
| WEIGHTS=output/tiny-yolo-balltote-train_300.weights | ||
| #darknet detector recall cfg/balltote.data cfg/tiny-yolo-balltote-train.cfg output/tiny-yolo-balltote-train_300.weights | ||
| darknet detector recall ${TEST} ${CFG} ${WEIGHTS} | ||
|
|
| @@ -0,0 +1,11 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| # note: had to chage hard-coded path to 2007_test.txt in yolo.c | ||
|
|
||
| #darknet yolo valid cfg/yolo-voc.2.0.test.cfg weights/yolo-voc-trained-1000.weights | ||
| #WEIGHTS=weights/yolo-2class-1000-dn448.weights | ||
| WEIGHTS=weights/yolo-2class.3000.weights | ||
| CFG=cfg/yolo-2class.cfg | ||
| TEST=/home/dean/data/stop-yield-data/train.list | ||
|
|
||
| darknet detector recall ${TEST} ${CFG} ${WEIGHTS} |
| @@ -0,0 +1,13 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| # note: had to chage hard-coded path to 2007_test.txt in yolo.c | ||
|
|
||
| TEST=/home/dean/AI/darknet/data/2007_test.txt | ||
| CFG=cfg/tiny-yolo-voc.train.cfg | ||
|
|
||
| WEIGHTS=weights/tiny-yolo-voc.weights | ||
|
|
||
| #darknet yolo valid cfg/yolo-voc.2.0.test.cfg weights/yolo-voc-trained-1000.weights | ||
| #darknet detector recall cfg/voc.data cfg/tiny-yolo-voc.train.cfg weights/tiny-yolo-voc.weights | ||
| darknet detector recall ${TEST} ${CFG} ${WEIGHTS} | ||
|
|
| @@ -0,0 +1,5 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| # note: had to chage hard-coded path to 2007_test.txt in yolo.c | ||
| #darknet yolo valid cfg/yolo-voc.2.0.test.cfg weights/yolo-voc-trained-1000.weights | ||
| darknet detector recall cfg/voc.data cfg/yolo-voc.2.0.test.cfg weights/yolo-voc_final.weights |
| @@ -0,0 +1,59 @@ | ||
| import xml.etree.ElementTree as ET | ||
| import pickle | ||
| import os | ||
| from os import listdir, getcwd | ||
| from os.path import join | ||
|
|
||
| sets=[('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')] | ||
|
|
||
| classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"] | ||
|
|
||
|
|
||
| def convert(size, box): | ||
| dw = 1./(size[0]) | ||
| dh = 1./(size[1]) | ||
| x = (box[0] + box[1])/2.0 - 1 | ||
| y = (box[2] + box[3])/2.0 - 1 | ||
| w = box[1] - box[0] | ||
| h = box[3] - box[2] | ||
| x = x*dw | ||
| w = w*dw | ||
| y = y*dh | ||
| h = h*dh | ||
| return (x,y,w,h) | ||
|
|
||
| def convert_annotation(year, image_id): | ||
| in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id)) | ||
| out_file = open('VOCdevkit/VOC%s/labels/%s.txt'%(year, image_id), 'w') | ||
| tree=ET.parse(in_file) | ||
| root = tree.getroot() | ||
| size = root.find('size') | ||
| w = int(size.find('width').text) | ||
| h = int(size.find('height').text) | ||
|
|
||
| for obj in root.iter('object'): | ||
| difficult = obj.find('difficult').text | ||
| cls = obj.find('name').text | ||
| if cls not in classes or int(difficult)==1: | ||
| continue | ||
| cls_id = classes.index(cls) | ||
| xmlbox = obj.find('bndbox') | ||
| b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text)) | ||
| bb = convert((w,h), b) | ||
| out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n') | ||
|
|
||
| wd = getcwd() | ||
|
|
||
| for year, image_set in sets: | ||
| if not os.path.exists('VOCdevkit/VOC%s/labels/'%(year)): | ||
| os.makedirs('VOCdevkit/VOC%s/labels/'%(year)) | ||
| image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split() | ||
| list_file = open('%s_%s.txt'%(year, image_set), 'w') | ||
| for image_id in image_ids: | ||
| list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id)) | ||
| convert_annotation(year, image_id) | ||
| list_file.close() | ||
|
|
||
| os.system("cat 2007_train.txt 2007_val.txt 2012_train.txt 2012_val.txt > train.txt") | ||
| os.system("cat 2007_train.txt 2007_val.txt 2007_test.txt 2012_train.txt 2012_val.txt > train.all.txt") | ||
|
|
| @@ -0,0 +1,8 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| #darknet yolo demo cfg/yolo_2class_box11.cfg weights/yolo_2class_box11_3000.weights data/YOLO_DEMO_Yield_Sign.mp4 | ||
|
|
||
| #darknet yolo demo -thresh 0.3 cfg/yolo-voc.2.0.cfg weights/yolo-voc_final.weights data/cartest2.mp4 | ||
| darknet yolo demo -thresh 0.3 cfg/tiny-yolo-voc.cfg weights/tiny-yolo-voc.weights data/cartest2.mp4 | ||
|
|
||
|
|
| @@ -0,0 +1,165 @@ | ||
| #include "cuda_runtime.h" | ||
| #include "curand.h" | ||
| #include "cublas_v2.h" | ||
|
|
||
| extern "C" { | ||
| #include "activations.h" | ||
| #include "cuda.h" | ||
| } | ||
|
|
||
|
|
||
| __device__ float lhtan_activate_kernel(float x) | ||
| { | ||
| if(x < 0) return .001*x; | ||
| if(x > 1) return .001*(x-1) + 1; | ||
| return x; | ||
| } | ||
| __device__ float lhtan_gradient_kernel(float x) | ||
| { | ||
| if(x > 0 && x < 1) return 1; | ||
| return .001; | ||
| } | ||
|
|
||
| __device__ float hardtan_activate_kernel(float x) | ||
| { | ||
| if (x < -1) return -1; | ||
| if (x > 1) return 1; | ||
| return x; | ||
| } | ||
| __device__ float linear_activate_kernel(float x){return x;} | ||
| __device__ float logistic_activate_kernel(float x){return 1./(1. + exp(-x));} | ||
| __device__ float loggy_activate_kernel(float x){return 2./(1. + exp(-x)) - 1;} | ||
| __device__ float relu_activate_kernel(float x){return x*(x>0);} | ||
| __device__ float elu_activate_kernel(float x){return (x >= 0)*x + (x < 0)*(exp(x)-1);} | ||
| __device__ float relie_activate_kernel(float x){return (x>0) ? x : .01*x;} | ||
| __device__ float ramp_activate_kernel(float x){return x*(x>0)+.1*x;} | ||
| __device__ float leaky_activate_kernel(float x){return (x>0) ? x : .1*x;} | ||
| __device__ float tanh_activate_kernel(float x){return (2/(1 + exp(-2*x)) - 1);} | ||
| __device__ float plse_activate_kernel(float x) | ||
| { | ||
| if(x < -4) return .01 * (x + 4); | ||
| if(x > 4) return .01 * (x - 4) + 1; | ||
| return .125*x + .5; | ||
| } | ||
| __device__ float stair_activate_kernel(float x) | ||
| { | ||
| int n = floor(x); | ||
| if (n%2 == 0) return floor(x/2.); | ||
| else return (x - n) + floor(x/2.); | ||
| } | ||
|
|
||
|
|
||
| __device__ float hardtan_gradient_kernel(float x) | ||
| { | ||
| if (x > -1 && x < 1) return 1; | ||
| return 0; | ||
| } | ||
| __device__ float linear_gradient_kernel(float x){return 1;} | ||
| __device__ float logistic_gradient_kernel(float x){return (1-x)*x;} | ||
| __device__ float loggy_gradient_kernel(float x) | ||
| { | ||
| float y = (x+1.)/2.; | ||
| return 2*(1-y)*y; | ||
| } | ||
| __device__ float relu_gradient_kernel(float x){return (x>0);} | ||
| __device__ float elu_gradient_kernel(float x){return (x >= 0) + (x < 0)*(x + 1);} | ||
| __device__ float relie_gradient_kernel(float x){return (x>0) ? 1 : .01;} | ||
| __device__ float ramp_gradient_kernel(float x){return (x>0)+.1;} | ||
| __device__ float leaky_gradient_kernel(float x){return (x>0) ? 1 : .1;} | ||
| __device__ float tanh_gradient_kernel(float x){return 1-x*x;} | ||
| __device__ float plse_gradient_kernel(float x){return (x < 0 || x > 1) ? .01 : .125;} | ||
| __device__ float stair_gradient_kernel(float x) | ||
| { | ||
| if (floor(x) == x) return 0; | ||
| return 1; | ||
| } | ||
|
|
||
| __device__ float activate_kernel(float x, ACTIVATION a) | ||
| { | ||
| switch(a){ | ||
| case LINEAR: | ||
| return linear_activate_kernel(x); | ||
| case LOGISTIC: | ||
| return logistic_activate_kernel(x); | ||
| case LOGGY: | ||
| return loggy_activate_kernel(x); | ||
| case RELU: | ||
| return relu_activate_kernel(x); | ||
| case ELU: | ||
| return elu_activate_kernel(x); | ||
| case RELIE: | ||
| return relie_activate_kernel(x); | ||
| case RAMP: | ||
| return ramp_activate_kernel(x); | ||
| case LEAKY: | ||
| return leaky_activate_kernel(x); | ||
| case TANH: | ||
| return tanh_activate_kernel(x); | ||
| case PLSE: | ||
| return plse_activate_kernel(x); | ||
| case STAIR: | ||
| return stair_activate_kernel(x); | ||
| case HARDTAN: | ||
| return hardtan_activate_kernel(x); | ||
| case LHTAN: | ||
| return lhtan_activate_kernel(x); | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| __device__ float gradient_kernel(float x, ACTIVATION a) | ||
| { | ||
| switch(a){ | ||
| case LINEAR: | ||
| return linear_gradient_kernel(x); | ||
| case LOGISTIC: | ||
| return logistic_gradient_kernel(x); | ||
| case LOGGY: | ||
| return loggy_gradient_kernel(x); | ||
| case RELU: | ||
| return relu_gradient_kernel(x); | ||
| case ELU: | ||
| return elu_gradient_kernel(x); | ||
| case RELIE: | ||
| return relie_gradient_kernel(x); | ||
| case RAMP: | ||
| return ramp_gradient_kernel(x); | ||
| case LEAKY: | ||
| return leaky_gradient_kernel(x); | ||
| case TANH: | ||
| return tanh_gradient_kernel(x); | ||
| case PLSE: | ||
| return plse_gradient_kernel(x); | ||
| case STAIR: | ||
| return stair_gradient_kernel(x); | ||
| case HARDTAN: | ||
| return hardtan_gradient_kernel(x); | ||
| case LHTAN: | ||
| return lhtan_gradient_kernel(x); | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| __global__ void activate_array_kernel(float *x, int n, ACTIVATION a) | ||
| { | ||
| int i = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x; | ||
| if(i < n) x[i] = activate_kernel(x[i], a); | ||
| } | ||
|
|
||
| __global__ void gradient_array_kernel(float *x, int n, ACTIVATION a, float *delta) | ||
| { | ||
| int i = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x; | ||
| if(i < n) delta[i] *= gradient_kernel(x[i], a); | ||
| } | ||
|
|
||
| extern "C" void activate_array_ongpu(float *x, int n, ACTIVATION a) | ||
| { | ||
| activate_array_kernel<<<cuda_gridsize(n), BLOCK>>>(x, n, a); | ||
| check_error(cudaPeekAtLastError()); | ||
| } | ||
|
|
||
| extern "C" void gradient_array_ongpu(float *x, int n, ACTIVATION a, float *delta) | ||
| { | ||
| gradient_array_kernel<<<cuda_gridsize(n), BLOCK>>>(x, n, a, delta); | ||
| check_error(cudaPeekAtLastError()); | ||
| } |
| @@ -0,0 +1,63 @@ | ||
| #include "activation_layer.h" | ||
| #include "utils.h" | ||
| #include "cuda.h" | ||
| #include "blas.h" | ||
| #include "gemm.h" | ||
|
|
||
| #include <math.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| layer make_activation_layer(int batch, int inputs, ACTIVATION activation) | ||
| { | ||
| layer l = {0}; | ||
| l.type = ACTIVE; | ||
|
|
||
| l.inputs = inputs; | ||
| l.outputs = inputs; | ||
| l.batch=batch; | ||
|
|
||
| l.output = calloc(batch*inputs, sizeof(float*)); | ||
| l.delta = calloc(batch*inputs, sizeof(float*)); | ||
|
|
||
| l.forward = forward_activation_layer; | ||
| l.backward = backward_activation_layer; | ||
| #ifdef GPU | ||
| l.forward_gpu = forward_activation_layer_gpu; | ||
| l.backward_gpu = backward_activation_layer_gpu; | ||
|
|
||
| l.output_gpu = cuda_make_array(l.output, inputs*batch); | ||
| l.delta_gpu = cuda_make_array(l.delta, inputs*batch); | ||
| #endif | ||
| l.activation = activation; | ||
| fprintf(stderr, "Activation Layer: %d inputs\n", inputs); | ||
| return l; | ||
| } | ||
|
|
||
| void forward_activation_layer(layer l, network net) | ||
| { | ||
| copy_cpu(l.outputs*l.batch, net.input, 1, l.output, 1); | ||
| activate_array(l.output, l.outputs*l.batch, l.activation); | ||
| } | ||
|
|
||
| void backward_activation_layer(layer l, network net) | ||
| { | ||
| gradient_array(l.output, l.outputs*l.batch, l.activation, l.delta); | ||
| copy_cpu(l.outputs*l.batch, l.delta, 1, net.delta, 1); | ||
| } | ||
|
|
||
| #ifdef GPU | ||
|
|
||
| void forward_activation_layer_gpu(layer l, network net) | ||
| { | ||
| copy_ongpu(l.outputs*l.batch, net.input_gpu, 1, l.output_gpu, 1); | ||
| activate_array_ongpu(l.output_gpu, l.outputs*l.batch, l.activation); | ||
| } | ||
|
|
||
| void backward_activation_layer_gpu(layer l, network net) | ||
| { | ||
| gradient_array_ongpu(l.output_gpu, l.outputs*l.batch, l.activation, l.delta_gpu); | ||
| copy_ongpu(l.outputs*l.batch, l.delta_gpu, 1, net.delta_gpu, 1); | ||
| } | ||
| #endif |
| @@ -0,0 +1,19 @@ | ||
| #ifndef ACTIVATION_LAYER_H | ||
| #define ACTIVATION_LAYER_H | ||
|
|
||
| #include "activations.h" | ||
| #include "layer.h" | ||
| #include "network.h" | ||
|
|
||
| layer make_activation_layer(int batch, int inputs, ACTIVATION activation); | ||
|
|
||
| void forward_activation_layer(layer l, network net); | ||
| void backward_activation_layer(layer l, network net); | ||
|
|
||
| #ifdef GPU | ||
| void forward_activation_layer_gpu(layer l, network net); | ||
| void backward_activation_layer_gpu(layer l, network net); | ||
| #endif | ||
|
|
||
| #endif | ||
|
|
| @@ -0,0 +1,143 @@ | ||
| #include "activations.h" | ||
|
|
||
| #include <math.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
|
|
||
| char *get_activation_string(ACTIVATION a) | ||
| { | ||
| switch(a){ | ||
| case LOGISTIC: | ||
| return "logistic"; | ||
| case LOGGY: | ||
| return "loggy"; | ||
| case RELU: | ||
| return "relu"; | ||
| case ELU: | ||
| return "elu"; | ||
| case RELIE: | ||
| return "relie"; | ||
| case RAMP: | ||
| return "ramp"; | ||
| case LINEAR: | ||
| return "linear"; | ||
| case TANH: | ||
| return "tanh"; | ||
| case PLSE: | ||
| return "plse"; | ||
| case LEAKY: | ||
| return "leaky"; | ||
| case STAIR: | ||
| return "stair"; | ||
| case HARDTAN: | ||
| return "hardtan"; | ||
| case LHTAN: | ||
| return "lhtan"; | ||
| default: | ||
| break; | ||
| } | ||
| return "relu"; | ||
| } | ||
|
|
||
| ACTIVATION get_activation(char *s) | ||
| { | ||
| if (strcmp(s, "logistic")==0) return LOGISTIC; | ||
| if (strcmp(s, "loggy")==0) return LOGGY; | ||
| if (strcmp(s, "relu")==0) return RELU; | ||
| if (strcmp(s, "elu")==0) return ELU; | ||
| if (strcmp(s, "relie")==0) return RELIE; | ||
| if (strcmp(s, "plse")==0) return PLSE; | ||
| if (strcmp(s, "hardtan")==0) return HARDTAN; | ||
| if (strcmp(s, "lhtan")==0) return LHTAN; | ||
| if (strcmp(s, "linear")==0) return LINEAR; | ||
| if (strcmp(s, "ramp")==0) return RAMP; | ||
| if (strcmp(s, "leaky")==0) return LEAKY; | ||
| if (strcmp(s, "tanh")==0) return TANH; | ||
| if (strcmp(s, "stair")==0) return STAIR; | ||
| fprintf(stderr, "Couldn't find activation function %s, going with ReLU\n", s); | ||
| return RELU; | ||
| } | ||
|
|
||
| float activate(float x, ACTIVATION a) | ||
| { | ||
| switch(a){ | ||
| case LINEAR: | ||
| return linear_activate(x); | ||
| case LOGISTIC: | ||
| return logistic_activate(x); | ||
| case LOGGY: | ||
| return loggy_activate(x); | ||
| case RELU: | ||
| return relu_activate(x); | ||
| case ELU: | ||
| return elu_activate(x); | ||
| case RELIE: | ||
| return relie_activate(x); | ||
| case RAMP: | ||
| return ramp_activate(x); | ||
| case LEAKY: | ||
| return leaky_activate(x); | ||
| case TANH: | ||
| return tanh_activate(x); | ||
| case PLSE: | ||
| return plse_activate(x); | ||
| case STAIR: | ||
| return stair_activate(x); | ||
| case HARDTAN: | ||
| return hardtan_activate(x); | ||
| case LHTAN: | ||
| return lhtan_activate(x); | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| void activate_array(float *x, const int n, const ACTIVATION a) | ||
| { | ||
| int i; | ||
| for(i = 0; i < n; ++i){ | ||
| x[i] = activate(x[i], a); | ||
| } | ||
| } | ||
|
|
||
| float gradient(float x, ACTIVATION a) | ||
| { | ||
| switch(a){ | ||
| case LINEAR: | ||
| return linear_gradient(x); | ||
| case LOGISTIC: | ||
| return logistic_gradient(x); | ||
| case LOGGY: | ||
| return loggy_gradient(x); | ||
| case RELU: | ||
| return relu_gradient(x); | ||
| case ELU: | ||
| return elu_gradient(x); | ||
| case RELIE: | ||
| return relie_gradient(x); | ||
| case RAMP: | ||
| return ramp_gradient(x); | ||
| case LEAKY: | ||
| return leaky_gradient(x); | ||
| case TANH: | ||
| return tanh_gradient(x); | ||
| case PLSE: | ||
| return plse_gradient(x); | ||
| case STAIR: | ||
| return stair_gradient(x); | ||
| case HARDTAN: | ||
| return hardtan_gradient(x); | ||
| case LHTAN: | ||
| return lhtan_gradient(x); | ||
| } | ||
| return 0; | ||
| } | ||
|
|
||
| void gradient_array(const float *x, const int n, const ACTIVATION a, float *delta) | ||
| { | ||
| int i; | ||
| for(i = 0; i < n; ++i){ | ||
| delta[i] *= gradient(x[i], a); | ||
| } | ||
| } | ||
|
|
| @@ -0,0 +1,88 @@ | ||
| #ifndef ACTIVATIONS_H | ||
| #define ACTIVATIONS_H | ||
| #include "cuda.h" | ||
| #include "math.h" | ||
|
|
||
| typedef enum{ | ||
| LOGISTIC, RELU, RELIE, LINEAR, RAMP, TANH, PLSE, LEAKY, ELU, LOGGY, STAIR, HARDTAN, LHTAN | ||
| }ACTIVATION; | ||
|
|
||
| ACTIVATION get_activation(char *s); | ||
|
|
||
| char *get_activation_string(ACTIVATION a); | ||
| float activate(float x, ACTIVATION a); | ||
| float gradient(float x, ACTIVATION a); | ||
| void gradient_array(const float *x, const int n, const ACTIVATION a, float *delta); | ||
| void activate_array(float *x, const int n, const ACTIVATION a); | ||
| #ifdef GPU | ||
| void activate_array_ongpu(float *x, int n, ACTIVATION a); | ||
| void gradient_array_ongpu(float *x, int n, ACTIVATION a, float *delta); | ||
| #endif | ||
|
|
||
| static inline float stair_activate(float x) | ||
| { | ||
| int n = floor(x); | ||
| if (n%2 == 0) return floor(x/2.); | ||
| else return (x - n) + floor(x/2.); | ||
| } | ||
| static inline float hardtan_activate(float x) | ||
| { | ||
| if (x < -1) return -1; | ||
| if (x > 1) return 1; | ||
| return x; | ||
| } | ||
| static inline float linear_activate(float x){return x;} | ||
| static inline float logistic_activate(float x){return 1./(1. + exp(-x));} | ||
| static inline float loggy_activate(float x){return 2./(1. + exp(-x)) - 1;} | ||
| static inline float relu_activate(float x){return x*(x>0);} | ||
| static inline float elu_activate(float x){return (x >= 0)*x + (x < 0)*(exp(x)-1);} | ||
| static inline float relie_activate(float x){return (x>0) ? x : .01*x;} | ||
| static inline float ramp_activate(float x){return x*(x>0)+.1*x;} | ||
| static inline float leaky_activate(float x){return (x>0) ? x : .1*x;} | ||
| static inline float tanh_activate(float x){return (exp(2*x)-1)/(exp(2*x)+1);} | ||
| static inline float plse_activate(float x) | ||
| { | ||
| if(x < -4) return .01 * (x + 4); | ||
| if(x > 4) return .01 * (x - 4) + 1; | ||
| return .125*x + .5; | ||
| } | ||
|
|
||
| static inline float lhtan_activate(float x) | ||
| { | ||
| if(x < 0) return .001*x; | ||
| if(x > 1) return .001*(x-1) + 1; | ||
| return x; | ||
| } | ||
| static inline float lhtan_gradient(float x) | ||
| { | ||
| if(x > 0 && x < 1) return 1; | ||
| return .001; | ||
| } | ||
|
|
||
| static inline float hardtan_gradient(float x) | ||
| { | ||
| if (x > -1 && x < 1) return 1; | ||
| return 0; | ||
| } | ||
| static inline float linear_gradient(float x){return 1;} | ||
| static inline float logistic_gradient(float x){return (1-x)*x;} | ||
| static inline float loggy_gradient(float x) | ||
| { | ||
| float y = (x+1.)/2.; | ||
| return 2*(1-y)*y; | ||
| } | ||
| static inline float stair_gradient(float x) | ||
| { | ||
| if (floor(x) == x) return 0; | ||
| return 1; | ||
| } | ||
| static inline float relu_gradient(float x){return (x>0);} | ||
| static inline float elu_gradient(float x){return (x >= 0) + (x < 0)*(x + 1);} | ||
| static inline float relie_gradient(float x){return (x>0) ? 1 : .01;} | ||
| static inline float ramp_gradient(float x){return (x>0)+.1;} | ||
| static inline float leaky_gradient(float x){return (x>0) ? 1 : .1;} | ||
| static inline float tanh_gradient(float x){return 1-x*x;} | ||
| static inline float plse_gradient(float x){return (x < 0 || x > 1) ? .01 : .125;} | ||
|
|
||
| #endif | ||
|
|
| @@ -0,0 +1,71 @@ | ||
| #include "network.h" | ||
| #include "utils.h" | ||
| #include "parser.h" | ||
| #include "option_list.h" | ||
| #include "blas.h" | ||
| #include "classifier.h" | ||
| #include <sys/time.h> | ||
|
|
||
| void demo_art(char *cfgfile, char *weightfile, int cam_index) | ||
| { | ||
| #ifdef OPENCV | ||
| network net = parse_network_cfg(cfgfile); | ||
| if(weightfile){ | ||
| load_weights(&net, weightfile); | ||
| } | ||
| set_batch_network(&net, 1); | ||
|
|
||
| srand(2222222); | ||
| CvCapture * cap; | ||
|
|
||
| cap = cvCaptureFromCAM(cam_index); | ||
|
|
||
| char *window = "ArtJudgementBot9000!!!"; | ||
| if(!cap) error("Couldn't connect to webcam.\n"); | ||
| cvNamedWindow(window, CV_WINDOW_NORMAL); | ||
| cvResizeWindow(window, 512, 512); | ||
| int i; | ||
| int idx[] = {37, 401, 434}; | ||
| int n = sizeof(idx)/sizeof(idx[0]); | ||
|
|
||
| while(1){ | ||
| image in = get_image_from_stream(cap); | ||
| image in_s = resize_image(in, net.w, net.h); | ||
| show_image(in, window); | ||
|
|
||
| float *p = network_predict(net, in_s.data); | ||
|
|
||
| printf("\033[2J"); | ||
| printf("\033[1;1H"); | ||
|
|
||
| float score = 0; | ||
| for(i = 0; i < n; ++i){ | ||
| float s = p[idx[i]]; | ||
| if (s > score) score = s; | ||
| } | ||
| score = score; | ||
| printf("I APPRECIATE THIS ARTWORK: %10.7f%%\n", score*100); | ||
| printf("["); | ||
| int upper = 30; | ||
| for(i = 0; i < upper; ++i){ | ||
| printf("%c", ((i+.5) < score*upper) ? 219 : ' '); | ||
| } | ||
| printf("]\n"); | ||
|
|
||
| free_image(in_s); | ||
| free_image(in); | ||
|
|
||
| cvWaitKey(1); | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
|
|
||
| void run_art(int argc, char **argv) | ||
| { | ||
| int cam_index = find_int_arg(argc, argv, "-c", 0); | ||
| char *cfg = argv[2]; | ||
| char *weights = argv[3]; | ||
| demo_art(cfg, weights, cam_index); | ||
| } | ||
|
|
| @@ -0,0 +1,71 @@ | ||
| #include "avgpool_layer.h" | ||
| #include "cuda.h" | ||
| #include <stdio.h> | ||
|
|
||
| avgpool_layer make_avgpool_layer(int batch, int w, int h, int c) | ||
| { | ||
| fprintf(stderr, "avg %4d x%4d x%4d -> %4d\n", w, h, c, c); | ||
| avgpool_layer l = {0}; | ||
| l.type = AVGPOOL; | ||
| l.batch = batch; | ||
| l.h = h; | ||
| l.w = w; | ||
| l.c = c; | ||
| l.out_w = 1; | ||
| l.out_h = 1; | ||
| l.out_c = c; | ||
| l.outputs = l.out_c; | ||
| l.inputs = h*w*c; | ||
| int output_size = l.outputs * batch; | ||
| l.output = calloc(output_size, sizeof(float)); | ||
| l.delta = calloc(output_size, sizeof(float)); | ||
| l.forward = forward_avgpool_layer; | ||
| l.backward = backward_avgpool_layer; | ||
| #ifdef GPU | ||
| l.forward_gpu = forward_avgpool_layer_gpu; | ||
| l.backward_gpu = backward_avgpool_layer_gpu; | ||
| l.output_gpu = cuda_make_array(l.output, output_size); | ||
| l.delta_gpu = cuda_make_array(l.delta, output_size); | ||
| #endif | ||
| return l; | ||
| } | ||
|
|
||
| void resize_avgpool_layer(avgpool_layer *l, int w, int h) | ||
| { | ||
| l->w = w; | ||
| l->h = h; | ||
| l->inputs = h*w*l->c; | ||
| } | ||
|
|
||
| void forward_avgpool_layer(const avgpool_layer l, network net) | ||
| { | ||
| int b,i,k; | ||
|
|
||
| for(b = 0; b < l.batch; ++b){ | ||
| for(k = 0; k < l.c; ++k){ | ||
| int out_index = k + b*l.c; | ||
| l.output[out_index] = 0; | ||
| for(i = 0; i < l.h*l.w; ++i){ | ||
| int in_index = i + l.h*l.w*(k + b*l.c); | ||
| l.output[out_index] += net.input[in_index]; | ||
| } | ||
| l.output[out_index] /= l.h*l.w; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void backward_avgpool_layer(const avgpool_layer l, network net) | ||
| { | ||
| int b,i,k; | ||
|
|
||
| for(b = 0; b < l.batch; ++b){ | ||
| for(k = 0; k < l.c; ++k){ | ||
| int out_index = k + b*l.c; | ||
| for(i = 0; i < l.h*l.w; ++i){ | ||
| int in_index = i + l.h*l.w*(k + b*l.c); | ||
| net.delta[in_index] += l.delta[out_index] / (l.h*l.w); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
| @@ -0,0 +1,23 @@ | ||
| #ifndef AVGPOOL_LAYER_H | ||
| #define AVGPOOL_LAYER_H | ||
|
|
||
| #include "image.h" | ||
| #include "cuda.h" | ||
| #include "layer.h" | ||
| #include "network.h" | ||
|
|
||
| typedef layer avgpool_layer; | ||
|
|
||
| image get_avgpool_image(avgpool_layer l); | ||
| avgpool_layer make_avgpool_layer(int batch, int w, int h, int c); | ||
| void resize_avgpool_layer(avgpool_layer *l, int w, int h); | ||
| void forward_avgpool_layer(const avgpool_layer l, network net); | ||
| void backward_avgpool_layer(const avgpool_layer l, network net); | ||
|
|
||
| #ifdef GPU | ||
| void forward_avgpool_layer_gpu(avgpool_layer l, network net); | ||
| void backward_avgpool_layer_gpu(avgpool_layer l, network net); | ||
| #endif | ||
|
|
||
| #endif | ||
|
|
| @@ -0,0 +1,61 @@ | ||
| #include "cuda_runtime.h" | ||
| #include "curand.h" | ||
| #include "cublas_v2.h" | ||
|
|
||
| extern "C" { | ||
| #include "avgpool_layer.h" | ||
| #include "cuda.h" | ||
| } | ||
|
|
||
| __global__ void forward_avgpool_layer_kernel(int n, int w, int h, int c, float *input, float *output) | ||
| { | ||
| int id = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x; | ||
| if(id >= n) return; | ||
|
|
||
| int k = id % c; | ||
| id /= c; | ||
| int b = id; | ||
|
|
||
| int i; | ||
| int out_index = (k + c*b); | ||
| output[out_index] = 0; | ||
| for(i = 0; i < w*h; ++i){ | ||
| int in_index = i + h*w*(k + b*c); | ||
| output[out_index] += input[in_index]; | ||
| } | ||
| output[out_index] /= w*h; | ||
| } | ||
|
|
||
| __global__ void backward_avgpool_layer_kernel(int n, int w, int h, int c, float *in_delta, float *out_delta) | ||
| { | ||
| int id = (blockIdx.x + blockIdx.y*gridDim.x) * blockDim.x + threadIdx.x; | ||
| if(id >= n) return; | ||
|
|
||
| int k = id % c; | ||
| id /= c; | ||
| int b = id; | ||
|
|
||
| int i; | ||
| int out_index = (k + c*b); | ||
| for(i = 0; i < w*h; ++i){ | ||
| int in_index = i + h*w*(k + b*c); | ||
| in_delta[in_index] += out_delta[out_index] / (w*h); | ||
| } | ||
| } | ||
|
|
||
| extern "C" void forward_avgpool_layer_gpu(avgpool_layer layer, network net) | ||
| { | ||
| size_t n = layer.c*layer.batch; | ||
|
|
||
| forward_avgpool_layer_kernel<<<cuda_gridsize(n), BLOCK>>>(n, layer.w, layer.h, layer.c, net.input_gpu, layer.output_gpu); | ||
| check_error(cudaPeekAtLastError()); | ||
| } | ||
|
|
||
| extern "C" void backward_avgpool_layer_gpu(avgpool_layer layer, network net) | ||
| { | ||
| size_t n = layer.c*layer.batch; | ||
|
|
||
| backward_avgpool_layer_kernel<<<cuda_gridsize(n), BLOCK>>>(n, layer.w, layer.h, layer.c, net.delta_gpu, layer.delta_gpu); | ||
| check_error(cudaPeekAtLastError()); | ||
| } | ||
|
|
| @@ -0,0 +1,287 @@ | ||
| #include "convolutional_layer.h" | ||
| #include "batchnorm_layer.h" | ||
| #include "blas.h" | ||
| #include <stdio.h> | ||
|
|
||
| layer make_batchnorm_layer(int batch, int w, int h, int c) | ||
| { | ||
| fprintf(stderr, "Batch Normalization Layer: %d x %d x %d image\n", w,h,c); | ||
| layer l = {0}; | ||
| l.type = BATCHNORM; | ||
| l.batch = batch; | ||
| l.h = l.out_h = h; | ||
| l.w = l.out_w = w; | ||
| l.c = l.out_c = c; | ||
| l.output = calloc(h * w * c * batch, sizeof(float)); | ||
| l.delta = calloc(h * w * c * batch, sizeof(float)); | ||
| l.inputs = w*h*c; | ||
| l.outputs = l.inputs; | ||
|
|
||
| l.scales = calloc(c, sizeof(float)); | ||
| l.scale_updates = calloc(c, sizeof(float)); | ||
| l.biases = calloc(c, sizeof(float)); | ||
| l.bias_updates = calloc(c, sizeof(float)); | ||
| int i; | ||
| for(i = 0; i < c; ++i){ | ||
| l.scales[i] = 1; | ||
| } | ||
|
|
||
| l.mean = calloc(c, sizeof(float)); | ||
| l.variance = calloc(c, sizeof(float)); | ||
|
|
||
| l.rolling_mean = calloc(c, sizeof(float)); | ||
| l.rolling_variance = calloc(c, sizeof(float)); | ||
|
|
||
| l.forward = forward_batchnorm_layer; | ||
| l.backward = backward_batchnorm_layer; | ||
| #ifdef GPU | ||
| l.forward_gpu = forward_batchnorm_layer_gpu; | ||
| l.backward_gpu = backward_batchnorm_layer_gpu; | ||
|
|
||
| l.output_gpu = cuda_make_array(l.output, h * w * c * batch); | ||
| l.delta_gpu = cuda_make_array(l.delta, h * w * c * batch); | ||
|
|
||
| l.biases_gpu = cuda_make_array(l.biases, c); | ||
| l.bias_updates_gpu = cuda_make_array(l.bias_updates, c); | ||
|
|
||
| l.scales_gpu = cuda_make_array(l.scales, c); | ||
| l.scale_updates_gpu = cuda_make_array(l.scale_updates, c); | ||
|
|
||
| l.mean_gpu = cuda_make_array(l.mean, c); | ||
| l.variance_gpu = cuda_make_array(l.variance, c); | ||
|
|
||
| l.rolling_mean_gpu = cuda_make_array(l.mean, c); | ||
| l.rolling_variance_gpu = cuda_make_array(l.variance, c); | ||
|
|
||
| l.mean_delta_gpu = cuda_make_array(l.mean, c); | ||
| l.variance_delta_gpu = cuda_make_array(l.variance, c); | ||
|
|
||
| l.x_gpu = cuda_make_array(l.output, l.batch*l.outputs); | ||
| l.x_norm_gpu = cuda_make_array(l.output, l.batch*l.outputs); | ||
| #ifdef CUDNN | ||
| cudnnCreateTensorDescriptor(&l.normTensorDesc); | ||
| cudnnCreateTensorDescriptor(&l.dstTensorDesc); | ||
| cudnnSetTensor4dDescriptor(l.dstTensorDesc, CUDNN_TENSOR_NCHW, CUDNN_DATA_FLOAT, l.batch, l.out_c, l.out_h, l.out_w); | ||
| cudnnSetTensor4dDescriptor(l.normTensorDesc, CUDNN_TENSOR_NCHW, CUDNN_DATA_FLOAT, 1, l.out_c, 1, 1); | ||
|
|
||
| #endif | ||
| #endif | ||
| return l; | ||
| } | ||
|
|
||
| void backward_scale_cpu(float *x_norm, float *delta, int batch, int n, int size, float *scale_updates) | ||
| { | ||
| int i,b,f; | ||
| for(f = 0; f < n; ++f){ | ||
| float sum = 0; | ||
| for(b = 0; b < batch; ++b){ | ||
| for(i = 0; i < size; ++i){ | ||
| int index = i + size*(f + n*b); | ||
| sum += delta[index] * x_norm[index]; | ||
| } | ||
| } | ||
| scale_updates[f] += sum; | ||
| } | ||
| } | ||
|
|
||
| void mean_delta_cpu(float *delta, float *variance, int batch, int filters, int spatial, float *mean_delta) | ||
| { | ||
|
|
||
| int i,j,k; | ||
| for(i = 0; i < filters; ++i){ | ||
| mean_delta[i] = 0; | ||
| for (j = 0; j < batch; ++j) { | ||
| for (k = 0; k < spatial; ++k) { | ||
| int index = j*filters*spatial + i*spatial + k; | ||
| mean_delta[i] += delta[index]; | ||
| } | ||
| } | ||
| mean_delta[i] *= (-1./sqrt(variance[i] + .00001f)); | ||
| } | ||
| } | ||
| void variance_delta_cpu(float *x, float *delta, float *mean, float *variance, int batch, int filters, int spatial, float *variance_delta) | ||
| { | ||
|
|
||
| int i,j,k; | ||
| for(i = 0; i < filters; ++i){ | ||
| variance_delta[i] = 0; | ||
| for(j = 0; j < batch; ++j){ | ||
| for(k = 0; k < spatial; ++k){ | ||
| int index = j*filters*spatial + i*spatial + k; | ||
| variance_delta[i] += delta[index]*(x[index] - mean[i]); | ||
| } | ||
| } | ||
| variance_delta[i] *= -.5 * pow(variance[i] + .00001f, (float)(-3./2.)); | ||
| } | ||
| } | ||
| void normalize_delta_cpu(float *x, float *mean, float *variance, float *mean_delta, float *variance_delta, int batch, int filters, int spatial, float *delta) | ||
| { | ||
| int f, j, k; | ||
| for(j = 0; j < batch; ++j){ | ||
| for(f = 0; f < filters; ++f){ | ||
| for(k = 0; k < spatial; ++k){ | ||
| int index = j*filters*spatial + f*spatial + k; | ||
| delta[index] = delta[index] * 1./(sqrt(variance[f] + .00001f)) + variance_delta[f] * 2. * (x[index] - mean[f]) / (spatial * batch) + mean_delta[f]/(spatial*batch); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void resize_batchnorm_layer(layer *layer, int w, int h) | ||
| { | ||
| fprintf(stderr, "Not implemented\n"); | ||
| } | ||
|
|
||
| void forward_batchnorm_layer(layer l, network net) | ||
| { | ||
| if(l.type == BATCHNORM) copy_cpu(l.outputs*l.batch, net.input, 1, l.output, 1); | ||
| if(l.type == CONNECTED){ | ||
| l.out_c = l.outputs; | ||
| l.out_h = l.out_w = 1; | ||
| } | ||
| copy_cpu(l.outputs*l.batch, l.output, 1, l.x, 1); | ||
| if(net.train){ | ||
| mean_cpu(l.output, l.batch, l.out_c, l.out_h*l.out_w, l.mean); | ||
| variance_cpu(l.output, l.mean, l.batch, l.out_c, l.out_h*l.out_w, l.variance); | ||
|
|
||
| scal_cpu(l.out_c, .99, l.rolling_mean, 1); | ||
| axpy_cpu(l.out_c, .01, l.mean, 1, l.rolling_mean, 1); | ||
| scal_cpu(l.out_c, .99, l.rolling_variance, 1); | ||
| axpy_cpu(l.out_c, .01, l.variance, 1, l.rolling_variance, 1); | ||
|
|
||
| normalize_cpu(l.output, l.mean, l.variance, l.batch, l.out_c, l.out_h*l.out_w); | ||
| copy_cpu(l.outputs*l.batch, l.output, 1, l.x_norm, 1); | ||
| } else { | ||
| normalize_cpu(l.output, l.rolling_mean, l.rolling_variance, l.batch, l.out_c, l.out_h*l.out_w); | ||
| } | ||
| scale_bias(l.output, l.scales, l.batch, l.out_c, l.out_h*l.out_w); | ||
| add_bias(l.output, l.biases, l.batch, l.out_c, l.out_h*l.out_w); | ||
| } | ||
|
|
||
| void backward_batchnorm_layer(layer l, network net) | ||
| { | ||
| if(!net.train){ | ||
| l.mean = l.rolling_mean; | ||
| l.variance = l.rolling_variance; | ||
| } | ||
| backward_bias(l.bias_updates, l.delta, l.batch, l.out_c, l.out_w*l.out_h); | ||
| backward_scale_cpu(l.x_norm, l.delta, l.batch, l.out_c, l.out_w*l.out_h, l.scale_updates); | ||
|
|
||
| scale_bias(l.delta, l.scales, l.batch, l.out_c, l.out_h*l.out_w); | ||
|
|
||
| mean_delta_cpu(l.delta, l.variance, l.batch, l.out_c, l.out_w*l.out_h, l.mean_delta); | ||
| variance_delta_cpu(l.x, l.delta, l.mean, l.variance, l.batch, l.out_c, l.out_w*l.out_h, l.variance_delta); | ||
| normalize_delta_cpu(l.x, l.mean, l.variance, l.mean_delta, l.variance_delta, l.batch, l.out_c, l.out_w*l.out_h, l.delta); | ||
| if(l.type == BATCHNORM) copy_cpu(l.outputs*l.batch, l.delta, 1, net.delta, 1); | ||
| } | ||
|
|
||
| #ifdef GPU | ||
|
|
||
| void pull_batchnorm_layer(layer l) | ||
| { | ||
| cuda_pull_array(l.scales_gpu, l.scales, l.c); | ||
| cuda_pull_array(l.rolling_mean_gpu, l.rolling_mean, l.c); | ||
| cuda_pull_array(l.rolling_variance_gpu, l.rolling_variance, l.c); | ||
| } | ||
| void push_batchnorm_layer(layer l) | ||
| { | ||
| cuda_push_array(l.scales_gpu, l.scales, l.c); | ||
| cuda_push_array(l.rolling_mean_gpu, l.rolling_mean, l.c); | ||
| cuda_push_array(l.rolling_variance_gpu, l.rolling_variance, l.c); | ||
| } | ||
|
|
||
| void forward_batchnorm_layer_gpu(layer l, network net) | ||
| { | ||
| if(l.type == BATCHNORM) copy_ongpu(l.outputs*l.batch, net.input_gpu, 1, l.output_gpu, 1); | ||
| if(l.type == CONNECTED){ | ||
| l.out_c = l.outputs; | ||
| l.out_h = l.out_w = 1; | ||
| } | ||
| copy_ongpu(l.outputs*l.batch, l.output_gpu, 1, l.x_gpu, 1); | ||
| if (net.train) { | ||
| #ifdef CUDNN | ||
| float one = 1; | ||
| float zero = 0; | ||
| cudnnBatchNormalizationForwardTraining(cudnn_handle(), | ||
| CUDNN_BATCHNORM_SPATIAL, | ||
| &one, | ||
| &zero, | ||
| l.dstTensorDesc, | ||
| l.x_gpu, | ||
| l.dstTensorDesc, | ||
| l.output_gpu, | ||
| l.normTensorDesc, | ||
| l.scales_gpu, | ||
| l.biases_gpu, | ||
| .01, | ||
| l.rolling_mean_gpu, | ||
| l.rolling_variance_gpu, | ||
| .00001, | ||
| l.mean_gpu, | ||
| l.variance_gpu); | ||
| #else | ||
| fast_mean_gpu(l.output_gpu, l.batch, l.out_c, l.out_h*l.out_w, l.mean_gpu); | ||
| fast_variance_gpu(l.output_gpu, l.mean_gpu, l.batch, l.out_c, l.out_h*l.out_w, l.variance_gpu); | ||
|
|
||
| scal_ongpu(l.out_c, .99, l.rolling_mean_gpu, 1); | ||
| axpy_ongpu(l.out_c, .01, l.mean_gpu, 1, l.rolling_mean_gpu, 1); | ||
| scal_ongpu(l.out_c, .99, l.rolling_variance_gpu, 1); | ||
| axpy_ongpu(l.out_c, .01, l.variance_gpu, 1, l.rolling_variance_gpu, 1); | ||
|
|
||
| copy_ongpu(l.outputs*l.batch, l.output_gpu, 1, l.x_gpu, 1); | ||
| normalize_gpu(l.output_gpu, l.mean_gpu, l.variance_gpu, l.batch, l.out_c, l.out_h*l.out_w); | ||
| copy_ongpu(l.outputs*l.batch, l.output_gpu, 1, l.x_norm_gpu, 1); | ||
|
|
||
| scale_bias_gpu(l.output_gpu, l.scales_gpu, l.batch, l.out_c, l.out_h*l.out_w); | ||
| add_bias_gpu(l.output_gpu, l.biases_gpu, l.batch, l.out_c, l.out_w*l.out_h); | ||
| #endif | ||
| } else { | ||
| normalize_gpu(l.output_gpu, l.rolling_mean_gpu, l.rolling_variance_gpu, l.batch, l.out_c, l.out_h*l.out_w); | ||
| scale_bias_gpu(l.output_gpu, l.scales_gpu, l.batch, l.out_c, l.out_h*l.out_w); | ||
| add_bias_gpu(l.output_gpu, l.biases_gpu, l.batch, l.out_c, l.out_w*l.out_h); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| void backward_batchnorm_layer_gpu(layer l, network net) | ||
| { | ||
| if(!net.train){ | ||
| l.mean_gpu = l.rolling_mean_gpu; | ||
| l.variance_gpu = l.rolling_variance_gpu; | ||
| } | ||
| #ifdef CUDNN | ||
| float one = 1; | ||
| float zero = 0; | ||
| cudnnBatchNormalizationBackward(cudnn_handle(), | ||
| CUDNN_BATCHNORM_SPATIAL, | ||
| &one, | ||
| &zero, | ||
| &one, | ||
| &one, | ||
| l.dstTensorDesc, | ||
| l.x_gpu, | ||
| l.dstTensorDesc, | ||
| l.delta_gpu, | ||
| l.dstTensorDesc, | ||
| l.x_norm_gpu, | ||
| l.normTensorDesc, | ||
| l.scales_gpu, | ||
| l.scale_updates_gpu, | ||
| l.bias_updates_gpu, | ||
| .00001, | ||
| l.mean_gpu, | ||
| l.variance_gpu); | ||
| copy_ongpu(l.outputs*l.batch, l.x_norm_gpu, 1, l.delta_gpu, 1); | ||
| #else | ||
| backward_bias_gpu(l.bias_updates_gpu, l.delta_gpu, l.batch, l.out_c, l.out_w*l.out_h); | ||
| backward_scale_gpu(l.x_norm_gpu, l.delta_gpu, l.batch, l.out_c, l.out_w*l.out_h, l.scale_updates_gpu); | ||
|
|
||
| scale_bias_gpu(l.delta_gpu, l.scales_gpu, l.batch, l.out_c, l.out_h*l.out_w); | ||
|
|
||
| fast_mean_delta_gpu(l.delta_gpu, l.variance_gpu, l.batch, l.out_c, l.out_w*l.out_h, l.mean_delta_gpu); | ||
| fast_variance_delta_gpu(l.x_gpu, l.delta_gpu, l.mean_gpu, l.variance_gpu, l.batch, l.out_c, l.out_w*l.out_h, l.variance_delta_gpu); | ||
| normalize_delta_gpu(l.x_gpu, l.mean_gpu, l.variance_gpu, l.mean_delta_gpu, l.variance_delta_gpu, l.batch, l.out_c, l.out_w*l.out_h, l.delta_gpu); | ||
| #endif | ||
| if(l.type == BATCHNORM) copy_ongpu(l.outputs*l.batch, l.delta_gpu, 1, net.delta_gpu, 1); | ||
| } | ||
| #endif |
| @@ -0,0 +1,19 @@ | ||
| #ifndef BATCHNORM_LAYER_H | ||
| #define BATCHNORM_LAYER_H | ||
|
|
||
| #include "image.h" | ||
| #include "layer.h" | ||
| #include "network.h" | ||
|
|
||
| layer make_batchnorm_layer(int batch, int w, int h, int c); | ||
| void forward_batchnorm_layer(layer l, network net); | ||
| void backward_batchnorm_layer(layer l, network net); | ||
|
|
||
| #ifdef GPU | ||
| void forward_batchnorm_layer_gpu(layer l, network net); | ||
| void backward_batchnorm_layer_gpu(layer l, network net); | ||
| void pull_batchnorm_layer(layer l); | ||
| void push_batchnorm_layer(layer l); | ||
| #endif | ||
|
|
||
| #endif |
| @@ -0,0 +1,243 @@ | ||
| #include "blas.h" | ||
| #include "math.h" | ||
| #include <assert.h> | ||
| #include <float.h> | ||
| #include <stdio.h> | ||
| #include <stdlib.h> | ||
| #include <string.h> | ||
| void reorg_cpu(float *x, int w, int h, int c, int batch, int stride, int forward, float *out) | ||
| { | ||
| int b,i,j,k; | ||
| int out_c = c/(stride*stride); | ||
|
|
||
| for(b = 0; b < batch; ++b){ | ||
| for(k = 0; k < c; ++k){ | ||
| for(j = 0; j < h; ++j){ | ||
| for(i = 0; i < w; ++i){ | ||
| int in_index = i + w*(j + h*(k + c*b)); | ||
| int c2 = k % out_c; | ||
| int offset = k / out_c; | ||
| int w2 = i*stride + offset % stride; | ||
| int h2 = j*stride + offset / stride; | ||
| int out_index = w2 + w*stride*(h2 + h*stride*(c2 + out_c*b)); | ||
| if(forward) out[out_index] = x[in_index]; | ||
| else out[in_index] = x[out_index]; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void flatten(float *x, int size, int layers, int batch, int forward) | ||
| { | ||
| float *swap = calloc(size*layers*batch, sizeof(float)); | ||
| int i,c,b; | ||
| for(b = 0; b < batch; ++b){ | ||
| for(c = 0; c < layers; ++c){ | ||
| for(i = 0; i < size; ++i){ | ||
| int i1 = b*layers*size + c*size + i; | ||
| int i2 = b*layers*size + i*layers + c; | ||
| if (forward) swap[i2] = x[i1]; | ||
| else swap[i1] = x[i2]; | ||
| } | ||
| } | ||
| } | ||
| memcpy(x, swap, size*layers*batch*sizeof(float)); | ||
| free(swap); | ||
| } | ||
|
|
||
| void weighted_sum_cpu(float *a, float *b, float *s, int n, float *c) | ||
| { | ||
| int i; | ||
| for(i = 0; i < n; ++i){ | ||
| c[i] = s[i]*a[i] + (1-s[i])*(b ? b[i] : 0); | ||
| } | ||
| } | ||
|
|
||
| void shortcut_cpu(int batch, int w1, int h1, int c1, float *add, int w2, int h2, int c2, float *out) | ||
| { | ||
| int stride = w1/w2; | ||
| int sample = w2/w1; | ||
| assert(stride == h1/h2); | ||
| assert(sample == h2/h1); | ||
| if(stride < 1) stride = 1; | ||
| if(sample < 1) sample = 1; | ||
| int minw = (w1 < w2) ? w1 : w2; | ||
| int minh = (h1 < h2) ? h1 : h2; | ||
| int minc = (c1 < c2) ? c1 : c2; | ||
|
|
||
| int i,j,k,b; | ||
| for(b = 0; b < batch; ++b){ | ||
| for(k = 0; k < minc; ++k){ | ||
| for(j = 0; j < minh; ++j){ | ||
| for(i = 0; i < minw; ++i){ | ||
| int out_index = i*sample + w2*(j*sample + h2*(k + c2*b)); | ||
| int add_index = i*stride + w1*(j*stride + h1*(k + c1*b)); | ||
| out[out_index] += add[add_index]; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void mean_cpu(float *x, int batch, int filters, int spatial, float *mean) | ||
| { | ||
| float scale = 1./(batch * spatial); | ||
| int i,j,k; | ||
| for(i = 0; i < filters; ++i){ | ||
| mean[i] = 0; | ||
| for(j = 0; j < batch; ++j){ | ||
| for(k = 0; k < spatial; ++k){ | ||
| int index = j*filters*spatial + i*spatial + k; | ||
| mean[i] += x[index]; | ||
| } | ||
| } | ||
| mean[i] *= scale; | ||
| } | ||
| } | ||
|
|
||
| void variance_cpu(float *x, float *mean, int batch, int filters, int spatial, float *variance) | ||
| { | ||
| float scale = 1./(batch * spatial - 1); | ||
| int i,j,k; | ||
| for(i = 0; i < filters; ++i){ | ||
| variance[i] = 0; | ||
| for(j = 0; j < batch; ++j){ | ||
| for(k = 0; k < spatial; ++k){ | ||
| int index = j*filters*spatial + i*spatial + k; | ||
| variance[i] += pow((x[index] - mean[i]), 2); | ||
| } | ||
| } | ||
| variance[i] *= scale; | ||
| } | ||
| } | ||
|
|
||
| void normalize_cpu(float *x, float *mean, float *variance, int batch, int filters, int spatial) | ||
| { | ||
| int b, f, i; | ||
| for(b = 0; b < batch; ++b){ | ||
| for(f = 0; f < filters; ++f){ | ||
| for(i = 0; i < spatial; ++i){ | ||
| int index = b*filters*spatial + f*spatial + i; | ||
| x[index] = (x[index] - mean[f])/(sqrt(variance[f]) + .000001f); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void const_cpu(int N, float ALPHA, float *X, int INCX) | ||
| { | ||
| int i; | ||
| for(i = 0; i < N; ++i) X[i*INCX] = ALPHA; | ||
| } | ||
|
|
||
| void mul_cpu(int N, float *X, int INCX, float *Y, int INCY) | ||
| { | ||
| int i; | ||
| for(i = 0; i < N; ++i) Y[i*INCY] *= X[i*INCX]; | ||
| } | ||
|
|
||
| void pow_cpu(int N, float ALPHA, float *X, int INCX, float *Y, int INCY) | ||
| { | ||
| int i; | ||
| for(i = 0; i < N; ++i) Y[i*INCY] = pow(X[i*INCX], ALPHA); | ||
| } | ||
|
|
||
| void axpy_cpu(int N, float ALPHA, float *X, int INCX, float *Y, int INCY) | ||
| { | ||
| int i; | ||
| for(i = 0; i < N; ++i) Y[i*INCY] += ALPHA*X[i*INCX]; | ||
| } | ||
|
|
||
| void scal_cpu(int N, float ALPHA, float *X, int INCX) | ||
| { | ||
| int i; | ||
| for(i = 0; i < N; ++i) X[i*INCX] *= ALPHA; | ||
| } | ||
|
|
||
| void fill_cpu(int N, float ALPHA, float *X, int INCX) | ||
| { | ||
| int i; | ||
| for(i = 0; i < N; ++i) X[i*INCX] = ALPHA; | ||
| } | ||
|
|
||
| void copy_cpu(int N, float *X, int INCX, float *Y, int INCY) | ||
| { | ||
| int i; | ||
| for(i = 0; i < N; ++i) Y[i*INCY] = X[i*INCX]; | ||
| } | ||
|
|
||
| void smooth_l1_cpu(int n, float *pred, float *truth, float *delta, float *error) | ||
| { | ||
| int i; | ||
| for(i = 0; i < n; ++i){ | ||
| float diff = truth[i] - pred[i]; | ||
| float abs_val = fabs(diff); | ||
| if(abs_val < 1) { | ||
| error[i] = diff * diff; | ||
| delta[i] = diff; | ||
| } | ||
| else { | ||
| error[i] = 2*abs_val - 1; | ||
| delta[i] = (diff < 0) ? 1 : -1; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void l1_cpu(int n, float *pred, float *truth, float *delta, float *error) | ||
| { | ||
| int i; | ||
| for(i = 0; i < n; ++i){ | ||
| float diff = truth[i] - pred[i]; | ||
| error[i] = fabs(diff); | ||
| delta[i] = diff > 0 ? 1 : -1; | ||
| } | ||
| } | ||
|
|
||
| void l2_cpu(int n, float *pred, float *truth, float *delta, float *error) | ||
| { | ||
| int i; | ||
| for(i = 0; i < n; ++i){ | ||
| float diff = truth[i] - pred[i]; | ||
| error[i] = diff * diff; | ||
| delta[i] = diff; | ||
| } | ||
| } | ||
|
|
||
| float dot_cpu(int N, float *X, int INCX, float *Y, int INCY) | ||
| { | ||
| int i; | ||
| float dot = 0; | ||
| for(i = 0; i < N; ++i) dot += X[i*INCX] * Y[i*INCY]; | ||
| return dot; | ||
| } | ||
|
|
||
| void softmax(float *input, int n, float temp, int stride, float *output) | ||
| { | ||
| int i; | ||
| float sum = 0; | ||
| float largest = -FLT_MAX; | ||
| for(i = 0; i < n; ++i){ | ||
| if(input[i*stride] > largest) largest = input[i*stride]; | ||
| } | ||
| for(i = 0; i < n; ++i){ | ||
| float e = exp(input[i*stride]/temp - largest/temp); | ||
| sum += e; | ||
| output[i*stride] = e; | ||
| } | ||
| for(i = 0; i < n; ++i){ | ||
| output[i*stride] /= sum; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| void softmax_cpu(float *input, int n, int batch, int batch_offset, int groups, int group_offset, int stride, float temp, float *output) | ||
| { | ||
| int g, b; | ||
| for(b = 0; b < batch; ++b){ | ||
| for(g = 0; g < groups; ++g){ | ||
| softmax(input + b*batch_offset + g*group_offset, n, temp, stride, output + b*batch_offset + g*group_offset); | ||
| } | ||
| } | ||
| } | ||
|
|
| @@ -0,0 +1,91 @@ | ||
| #ifndef BLAS_H | ||
| #define BLAS_H | ||
| void flatten(float *x, int size, int layers, int batch, int forward); | ||
| void pm(int M, int N, float *A); | ||
| float *random_matrix(int rows, int cols); | ||
| void time_random_matrix(int TA, int TB, int m, int k, int n); | ||
| void reorg_cpu(float *x, int w, int h, int c, int batch, int stride, int forward, float *out); | ||
|
|
||
| void test_blas(); | ||
|
|
||
| void const_cpu(int N, float ALPHA, float *X, int INCX); | ||
| void constrain_ongpu(int N, float ALPHA, float * X, int INCX); | ||
| void pow_cpu(int N, float ALPHA, float *X, int INCX, float *Y, int INCY); | ||
| void mul_cpu(int N, float *X, int INCX, float *Y, int INCY); | ||
|
|
||
| void axpy_cpu(int N, float ALPHA, float *X, int INCX, float *Y, int INCY); | ||
| void copy_cpu(int N, float *X, int INCX, float *Y, int INCY); | ||
| void scal_cpu(int N, float ALPHA, float *X, int INCX); | ||
| void fill_cpu(int N, float ALPHA, float * X, int INCX); | ||
| float dot_cpu(int N, float *X, int INCX, float *Y, int INCY); | ||
| void test_gpu_blas(); | ||
| void shortcut_cpu(int batch, int w1, int h1, int c1, float *add, int w2, int h2, int c2, float *out); | ||
|
|
||
| void mean_cpu(float *x, int batch, int filters, int spatial, float *mean); | ||
| void variance_cpu(float *x, float *mean, int batch, int filters, int spatial, float *variance); | ||
| void normalize_cpu(float *x, float *mean, float *variance, int batch, int filters, int spatial); | ||
|
|
||
| void scale_bias(float *output, float *scales, int batch, int n, int size); | ||
| void backward_scale_cpu(float *x_norm, float *delta, int batch, int n, int size, float *scale_updates); | ||
| void mean_delta_cpu(float *delta, float *variance, int batch, int filters, int spatial, float *mean_delta); | ||
| void variance_delta_cpu(float *x, float *delta, float *mean, float *variance, int batch, int filters, int spatial, float *variance_delta); | ||
| void normalize_delta_cpu(float *x, float *mean, float *variance, float *mean_delta, float *variance_delta, int batch, int filters, int spatial, float *delta); | ||
|
|
||
| void smooth_l1_cpu(int n, float *pred, float *truth, float *delta, float *error); | ||
| void l2_cpu(int n, float *pred, float *truth, float *delta, float *error); | ||
| void l1_cpu(int n, float *pred, float *truth, float *delta, float *error); | ||
| void weighted_sum_cpu(float *a, float *b, float *s, int num, float *c); | ||
|
|
||
| void softmax(float *input, int n, float temp, int stride, float *output); | ||
| void softmax_cpu(float *input, int n, int batch, int batch_offset, int groups, int group_offset, int stride, float temp, float *output); | ||
|
|
||
| #ifdef GPU | ||
| #include "cuda.h" | ||
|
|
||
| void axpy_ongpu(int N, float ALPHA, float * X, int INCX, float * Y, int INCY); | ||
| void axpy_ongpu_offset(int N, float ALPHA, float * X, int OFFX, int INCX, float * Y, int OFFY, int INCY); | ||
| void copy_ongpu(int N, float * X, int INCX, float * Y, int INCY); | ||
| void copy_ongpu_offset(int N, float * X, int OFFX, int INCX, float * Y, int OFFY, int INCY); | ||
| void scal_ongpu(int N, float ALPHA, float * X, int INCX); | ||
| void add_ongpu(int N, float ALPHA, float * X, int INCX); | ||
| void supp_ongpu(int N, float ALPHA, float * X, int INCX); | ||
| void mask_ongpu(int N, float * X, float mask_num, float * mask); | ||
| void const_ongpu(int N, float ALPHA, float *X, int INCX); | ||
| void pow_ongpu(int N, float ALPHA, float *X, int INCX, float *Y, int INCY); | ||
| void mul_ongpu(int N, float *X, int INCX, float *Y, int INCY); | ||
| void fill_ongpu(int N, float ALPHA, float * X, int INCX); | ||
|
|
||
| void mean_gpu(float *x, int batch, int filters, int spatial, float *mean); | ||
| void variance_gpu(float *x, float *mean, int batch, int filters, int spatial, float *variance); | ||
| void normalize_gpu(float *x, float *mean, float *variance, int batch, int filters, int spatial); | ||
|
|
||
| void normalize_delta_gpu(float *x, float *mean, float *variance, float *mean_delta, float *variance_delta, int batch, int filters, int spatial, float *delta); | ||
|
|
||
| void fast_mean_delta_gpu(float *delta, float *variance, int batch, int filters, int spatial, float *mean_delta); | ||
| void fast_variance_delta_gpu(float *x, float *delta, float *mean, float *variance, int batch, int filters, int spatial, float *variance_delta); | ||
|
|
||
| void fast_variance_gpu(float *x, float *mean, int batch, int filters, int spatial, float *variance); | ||
| void fast_mean_gpu(float *x, int batch, int filters, int spatial, float *mean); | ||
| void shortcut_gpu(int batch, int w1, int h1, int c1, float *add, int w2, int h2, int c2, float *out); | ||
| void scale_bias_gpu(float *output, float *biases, int batch, int n, int size); | ||
| void backward_scale_gpu(float *x_norm, float *delta, int batch, int n, int size, float *scale_updates); | ||
| void scale_bias_gpu(float *output, float *biases, int batch, int n, int size); | ||
| void add_bias_gpu(float *output, float *biases, int batch, int n, int size); | ||
| void backward_bias_gpu(float *bias_updates, float *delta, int batch, int n, int size); | ||
|
|
||
| void smooth_l1_gpu(int n, float *pred, float *truth, float *delta, float *error); | ||
| void l2_gpu(int n, float *pred, float *truth, float *delta, float *error); | ||
| void l1_gpu(int n, float *pred, float *truth, float *delta, float *error); | ||
| void weighted_delta_gpu(float *a, float *b, float *s, float *da, float *db, float *ds, int num, float *dc); | ||
| void weighted_sum_gpu(float *a, float *b, float *s, int num, float *c); | ||
| void mult_add_into_gpu(int num, float *a, float *b, float *c); | ||
|
|
||
| void reorg_ongpu(float *x, int w, int h, int c, int batch, int stride, int forward, float *out); | ||
|
|
||
| void softmax_gpu(float *input, int n, int batch, int batch_offset, int groups, int group_offset, int stride, float temp, float *output); | ||
| void adam_gpu(int n, float *x, float *m, float *v, float B1, float B2, float rate, float eps, int t); | ||
|
|
||
| void flatten_ongpu(float *x, int spatial, int layers, int batch, int forward, float *out); | ||
|
|
||
| #endif | ||
| #endif |
| @@ -0,0 +1,345 @@ | ||
| #include "box.h" | ||
| #include <stdio.h> | ||
| #include <math.h> | ||
| #include <stdlib.h> | ||
|
|
||
| box float_to_box(float *f, int stride) | ||
| { | ||
| box b; | ||
| b.x = f[0]; | ||
| b.y = f[1*stride]; | ||
| b.w = f[2*stride]; | ||
| b.h = f[3*stride]; | ||
| return b; | ||
| } | ||
|
|
||
| dbox derivative(box a, box b) | ||
| { | ||
| dbox d; | ||
| d.dx = 0; | ||
| d.dw = 0; | ||
| float l1 = a.x - a.w/2; | ||
| float l2 = b.x - b.w/2; | ||
| if (l1 > l2){ | ||
| d.dx -= 1; | ||
| d.dw += .5; | ||
| } | ||
| float r1 = a.x + a.w/2; | ||
| float r2 = b.x + b.w/2; | ||
| if(r1 < r2){ | ||
| d.dx += 1; | ||
| d.dw += .5; | ||
| } | ||
| if (l1 > r2) { | ||
| d.dx = -1; | ||
| d.dw = 0; | ||
| } | ||
| if (r1 < l2){ | ||
| d.dx = 1; | ||
| d.dw = 0; | ||
| } | ||
|
|
||
| d.dy = 0; | ||
| d.dh = 0; | ||
| float t1 = a.y - a.h/2; | ||
| float t2 = b.y - b.h/2; | ||
| if (t1 > t2){ | ||
| d.dy -= 1; | ||
| d.dh += .5; | ||
| } | ||
| float b1 = a.y + a.h/2; | ||
| float b2 = b.y + b.h/2; | ||
| if(b1 < b2){ | ||
| d.dy += 1; | ||
| d.dh += .5; | ||
| } | ||
| if (t1 > b2) { | ||
| d.dy = -1; | ||
| d.dh = 0; | ||
| } | ||
| if (b1 < t2){ | ||
| d.dy = 1; | ||
| d.dh = 0; | ||
| } | ||
| return d; | ||
| } | ||
|
|
||
| float overlap(float x1, float w1, float x2, float w2) | ||
| { | ||
| float l1 = x1 - w1/2; | ||
| float l2 = x2 - w2/2; | ||
| float left = l1 > l2 ? l1 : l2; | ||
| float r1 = x1 + w1/2; | ||
| float r2 = x2 + w2/2; | ||
| float right = r1 < r2 ? r1 : r2; | ||
| return right - left; | ||
| } | ||
|
|
||
| float box_intersection(box a, box b) | ||
| { | ||
| float w = overlap(a.x, a.w, b.x, b.w); | ||
| float h = overlap(a.y, a.h, b.y, b.h); | ||
| if(w < 0 || h < 0) return 0; | ||
| float area = w*h; | ||
| return area; | ||
| } | ||
|
|
||
| float box_union(box a, box b) | ||
| { | ||
| float i = box_intersection(a, b); | ||
| float u = a.w*a.h + b.w*b.h - i; | ||
| return u; | ||
| } | ||
|
|
||
| float box_iou(box a, box b) | ||
| { | ||
| return box_intersection(a, b)/box_union(a, b); | ||
| } | ||
|
|
||
| float box_rmse(box a, box b) | ||
| { | ||
| return sqrt(pow(a.x-b.x, 2) + | ||
| pow(a.y-b.y, 2) + | ||
| pow(a.w-b.w, 2) + | ||
| pow(a.h-b.h, 2)); | ||
| } | ||
|
|
||
| dbox dintersect(box a, box b) | ||
| { | ||
| float w = overlap(a.x, a.w, b.x, b.w); | ||
| float h = overlap(a.y, a.h, b.y, b.h); | ||
| dbox dover = derivative(a, b); | ||
| dbox di; | ||
|
|
||
| di.dw = dover.dw*h; | ||
| di.dx = dover.dx*h; | ||
| di.dh = dover.dh*w; | ||
| di.dy = dover.dy*w; | ||
|
|
||
| return di; | ||
| } | ||
|
|
||
| dbox dunion(box a, box b) | ||
| { | ||
| dbox du; | ||
|
|
||
| dbox di = dintersect(a, b); | ||
| du.dw = a.h - di.dw; | ||
| du.dh = a.w - di.dh; | ||
| du.dx = -di.dx; | ||
| du.dy = -di.dy; | ||
|
|
||
| return du; | ||
| } | ||
|
|
||
|
|
||
| void test_dunion() | ||
| { | ||
| box a = {0, 0, 1, 1}; | ||
| box dxa= {0+.0001, 0, 1, 1}; | ||
| box dya= {0, 0+.0001, 1, 1}; | ||
| box dwa= {0, 0, 1+.0001, 1}; | ||
| box dha= {0, 0, 1, 1+.0001}; | ||
|
|
||
| box b = {.5, .5, .2, .2}; | ||
| dbox di = dunion(a,b); | ||
| printf("Union: %f %f %f %f\n", di.dx, di.dy, di.dw, di.dh); | ||
| float inter = box_union(a, b); | ||
| float xinter = box_union(dxa, b); | ||
| float yinter = box_union(dya, b); | ||
| float winter = box_union(dwa, b); | ||
| float hinter = box_union(dha, b); | ||
| xinter = (xinter - inter)/(.0001); | ||
| yinter = (yinter - inter)/(.0001); | ||
| winter = (winter - inter)/(.0001); | ||
| hinter = (hinter - inter)/(.0001); | ||
| printf("Union Manual %f %f %f %f\n", xinter, yinter, winter, hinter); | ||
| } | ||
| void test_dintersect() | ||
| { | ||
| box a = {0, 0, 1, 1}; | ||
| box dxa= {0+.0001, 0, 1, 1}; | ||
| box dya= {0, 0+.0001, 1, 1}; | ||
| box dwa= {0, 0, 1+.0001, 1}; | ||
| box dha= {0, 0, 1, 1+.0001}; | ||
|
|
||
| box b = {.5, .5, .2, .2}; | ||
| dbox di = dintersect(a,b); | ||
| printf("Inter: %f %f %f %f\n", di.dx, di.dy, di.dw, di.dh); | ||
| float inter = box_intersection(a, b); | ||
| float xinter = box_intersection(dxa, b); | ||
| float yinter = box_intersection(dya, b); | ||
| float winter = box_intersection(dwa, b); | ||
| float hinter = box_intersection(dha, b); | ||
| xinter = (xinter - inter)/(.0001); | ||
| yinter = (yinter - inter)/(.0001); | ||
| winter = (winter - inter)/(.0001); | ||
| hinter = (hinter - inter)/(.0001); | ||
| printf("Inter Manual %f %f %f %f\n", xinter, yinter, winter, hinter); | ||
| } | ||
|
|
||
| void test_box() | ||
| { | ||
| test_dintersect(); | ||
| test_dunion(); | ||
| box a = {0, 0, 1, 1}; | ||
| box dxa= {0+.00001, 0, 1, 1}; | ||
| box dya= {0, 0+.00001, 1, 1}; | ||
| box dwa= {0, 0, 1+.00001, 1}; | ||
| box dha= {0, 0, 1, 1+.00001}; | ||
|
|
||
| box b = {.5, 0, .2, .2}; | ||
|
|
||
| float iou = box_iou(a,b); | ||
| iou = (1-iou)*(1-iou); | ||
| printf("%f\n", iou); | ||
| dbox d = diou(a, b); | ||
| printf("%f %f %f %f\n", d.dx, d.dy, d.dw, d.dh); | ||
|
|
||
| float xiou = box_iou(dxa, b); | ||
| float yiou = box_iou(dya, b); | ||
| float wiou = box_iou(dwa, b); | ||
| float hiou = box_iou(dha, b); | ||
| xiou = ((1-xiou)*(1-xiou) - iou)/(.00001); | ||
| yiou = ((1-yiou)*(1-yiou) - iou)/(.00001); | ||
| wiou = ((1-wiou)*(1-wiou) - iou)/(.00001); | ||
| hiou = ((1-hiou)*(1-hiou) - iou)/(.00001); | ||
| printf("manual %f %f %f %f\n", xiou, yiou, wiou, hiou); | ||
| } | ||
|
|
||
| dbox diou(box a, box b) | ||
| { | ||
| float u = box_union(a,b); | ||
| float i = box_intersection(a,b); | ||
| dbox di = dintersect(a,b); | ||
| dbox du = dunion(a,b); | ||
| dbox dd = {0,0,0,0}; | ||
|
|
||
| if(i <= 0 || 1) { | ||
| dd.dx = b.x - a.x; | ||
| dd.dy = b.y - a.y; | ||
| dd.dw = b.w - a.w; | ||
| dd.dh = b.h - a.h; | ||
| return dd; | ||
| } | ||
|
|
||
| dd.dx = 2*pow((1-(i/u)),1)*(di.dx*u - du.dx*i)/(u*u); | ||
| dd.dy = 2*pow((1-(i/u)),1)*(di.dy*u - du.dy*i)/(u*u); | ||
| dd.dw = 2*pow((1-(i/u)),1)*(di.dw*u - du.dw*i)/(u*u); | ||
| dd.dh = 2*pow((1-(i/u)),1)*(di.dh*u - du.dh*i)/(u*u); | ||
| return dd; | ||
| } | ||
|
|
||
| typedef struct{ | ||
| int index; | ||
| int class; | ||
| float **probs; | ||
| } sortable_bbox; | ||
|
|
||
| int nms_comparator(const void *pa, const void *pb) | ||
| { | ||
| sortable_bbox a = *(sortable_bbox *)pa; | ||
| sortable_bbox b = *(sortable_bbox *)pb; | ||
| float diff = a.probs[a.index][b.class] - b.probs[b.index][b.class]; | ||
| if(diff < 0) return 1; | ||
| else if(diff > 0) return -1; | ||
| return 0; | ||
| } | ||
|
|
||
| void do_nms_obj(box *boxes, float **probs, int total, int classes, float thresh) | ||
| { | ||
| int i, j, k; | ||
| sortable_bbox *s = calloc(total, sizeof(sortable_bbox)); | ||
|
|
||
| for(i = 0; i < total; ++i){ | ||
| s[i].index = i; | ||
| s[i].class = classes; | ||
| s[i].probs = probs; | ||
| } | ||
|
|
||
| qsort(s, total, sizeof(sortable_bbox), nms_comparator); | ||
| for(i = 0; i < total; ++i){ | ||
| if(probs[s[i].index][classes] == 0) continue; | ||
| box a = boxes[s[i].index]; | ||
| for(j = i+1; j < total; ++j){ | ||
| box b = boxes[s[j].index]; | ||
| if (box_iou(a, b) > thresh){ | ||
| for(k = 0; k < classes+1; ++k){ | ||
| probs[s[j].index][k] = 0; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| free(s); | ||
| } | ||
|
|
||
|
|
||
| void do_nms_sort(box *boxes, float **probs, int total, int classes, float thresh) | ||
| { | ||
| int i, j, k; | ||
| sortable_bbox *s = calloc(total, sizeof(sortable_bbox)); | ||
|
|
||
| for(i = 0; i < total; ++i){ | ||
| s[i].index = i; | ||
| s[i].class = 0; | ||
| s[i].probs = probs; | ||
| } | ||
|
|
||
| for(k = 0; k < classes; ++k){ | ||
| for(i = 0; i < total; ++i){ | ||
| s[i].class = k; | ||
| } | ||
| qsort(s, total, sizeof(sortable_bbox), nms_comparator); | ||
| for(i = 0; i < total; ++i){ | ||
| if(probs[s[i].index][k] == 0) continue; | ||
| box a = boxes[s[i].index]; | ||
| for(j = i+1; j < total; ++j){ | ||
| box b = boxes[s[j].index]; | ||
| if (box_iou(a, b) > thresh){ | ||
| probs[s[j].index][k] = 0; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| free(s); | ||
| } | ||
|
|
||
| void do_nms(box *boxes, float **probs, int total, int classes, float thresh) | ||
| { | ||
| int i, j, k; | ||
| for(i = 0; i < total; ++i){ | ||
| int any = 0; | ||
| for(k = 0; k < classes; ++k) any = any || (probs[i][k] > 0); | ||
| if(!any) { | ||
| continue; | ||
| } | ||
| for(j = i+1; j < total; ++j){ | ||
| if (box_iou(boxes[i], boxes[j]) > thresh){ | ||
| for(k = 0; k < classes; ++k){ | ||
| if (probs[i][k] < probs[j][k]) probs[i][k] = 0; | ||
| else probs[j][k] = 0; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| box encode_box(box b, box anchor) | ||
| { | ||
| box encode; | ||
| encode.x = (b.x - anchor.x) / anchor.w; | ||
| encode.y = (b.y - anchor.y) / anchor.h; | ||
| encode.w = log2(b.w / anchor.w); | ||
| encode.h = log2(b.h / anchor.h); | ||
| return encode; | ||
| } | ||
|
|
||
| box decode_box(box b, box anchor) | ||
| { | ||
| box decode; | ||
| decode.x = b.x * anchor.w + anchor.x; | ||
| decode.y = b.y * anchor.h + anchor.y; | ||
| decode.w = pow(2., b.w) * anchor.w; | ||
| decode.h = pow(2., b.h) * anchor.h; | ||
| return decode; | ||
| } |
| @@ -0,0 +1,22 @@ | ||
| #ifndef BOX_H | ||
| #define BOX_H | ||
|
|
||
| typedef struct{ | ||
| float x, y, w, h; | ||
| } box; | ||
|
|
||
| typedef struct{ | ||
| float dx, dy, dw, dh; | ||
| } dbox; | ||
|
|
||
| box float_to_box(float *f, int stride); | ||
| float box_iou(box a, box b); | ||
| float box_rmse(box a, box b); | ||
| dbox diou(box a, box b); | ||
| void do_nms(box *boxes, float **probs, int total, int classes, float thresh); | ||
| void do_nms_sort(box *boxes, float **probs, int total, int classes, float thresh); | ||
| void do_nms_obj(box *boxes, float **probs, int total, int classes, float thresh); | ||
| box decode_box(box b, box anchor); | ||
| box encode_box(box b, box anchor); | ||
|
|
||
| #endif |
| @@ -0,0 +1,364 @@ | ||
| #include "network.h" | ||
| #include "utils.h" | ||
| #include "parser.h" | ||
|
|
||
| void fix_data_captcha(data d, int mask) | ||
| { | ||
| matrix labels = d.y; | ||
| int i, j; | ||
| for(i = 0; i < d.y.rows; ++i){ | ||
| for(j = 0; j < d.y.cols; j += 2){ | ||
| if (mask){ | ||
| if(!labels.vals[i][j]){ | ||
| labels.vals[i][j] = SECRET_NUM; | ||
| labels.vals[i][j+1] = SECRET_NUM; | ||
| }else if(labels.vals[i][j+1]){ | ||
| labels.vals[i][j] = 0; | ||
| } | ||
| } else{ | ||
| if (labels.vals[i][j]) { | ||
| labels.vals[i][j+1] = 0; | ||
| } else { | ||
| labels.vals[i][j+1] = 1; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void train_captcha(char *cfgfile, char *weightfile) | ||
| { | ||
| srand(time(0)); | ||
| float avg_loss = -1; | ||
| char *base = basecfg(cfgfile); | ||
| printf("%s\n", base); | ||
| network net = parse_network_cfg(cfgfile); | ||
| if(weightfile){ | ||
| load_weights(&net, weightfile); | ||
| } | ||
| printf("Learning Rate: %g, Momentum: %g, Decay: %g\n", net.learning_rate, net.momentum, net.decay); | ||
| int imgs = 1024; | ||
| int i = *net.seen/imgs; | ||
| int solved = 1; | ||
| list *plist; | ||
| char **labels = get_labels("/data/captcha/reimgs.labels.list"); | ||
| if (solved){ | ||
| plist = get_paths("/data/captcha/reimgs.solved.list"); | ||
| }else{ | ||
| plist = get_paths("/data/captcha/reimgs.raw.list"); | ||
| } | ||
| char **paths = (char **)list_to_array(plist); | ||
| printf("%d\n", plist->size); | ||
| clock_t time; | ||
| pthread_t load_thread; | ||
| data train; | ||
| data buffer; | ||
|
|
||
| load_args args = {0}; | ||
| args.w = net.w; | ||
| args.h = net.h; | ||
| args.paths = paths; | ||
| args.classes = 26; | ||
| args.n = imgs; | ||
| args.m = plist->size; | ||
| args.labels = labels; | ||
| args.d = &buffer; | ||
| args.type = CLASSIFICATION_DATA; | ||
|
|
||
| load_thread = load_data_in_thread(args); | ||
| while(1){ | ||
| ++i; | ||
| time=clock(); | ||
| pthread_join(load_thread, 0); | ||
| train = buffer; | ||
| fix_data_captcha(train, solved); | ||
|
|
||
| /* | ||
| image im = float_to_image(256, 256, 3, train.X.vals[114]); | ||
| show_image(im, "training"); | ||
| cvWaitKey(0); | ||
| */ | ||
|
|
||
| load_thread = load_data_in_thread(args); | ||
| printf("Loaded: %lf seconds\n", sec(clock()-time)); | ||
| time=clock(); | ||
| float loss = train_network(net, train); | ||
| if(avg_loss == -1) avg_loss = loss; | ||
| avg_loss = avg_loss*.9 + loss*.1; | ||
| printf("%d: %f, %f avg, %lf seconds, %d images\n", i, loss, avg_loss, sec(clock()-time), *net.seen); | ||
| free_data(train); | ||
| if(i%100==0){ | ||
| char buff[256]; | ||
| sprintf(buff, "/home/pjreddie/imagenet_backup/%s_%d.weights",base, i); | ||
| save_weights(net, buff); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void test_captcha(char *cfgfile, char *weightfile, char *filename) | ||
| { | ||
| network net = parse_network_cfg(cfgfile); | ||
| if(weightfile){ | ||
| load_weights(&net, weightfile); | ||
| } | ||
| set_batch_network(&net, 1); | ||
| srand(2222222); | ||
| int i = 0; | ||
| char **names = get_labels("/data/captcha/reimgs.labels.list"); | ||
| char buff[256]; | ||
| char *input = buff; | ||
| int indexes[26]; | ||
| while(1){ | ||
| if(filename){ | ||
| strncpy(input, filename, 256); | ||
| }else{ | ||
| //printf("Enter Image Path: "); | ||
| //fflush(stdout); | ||
| input = fgets(input, 256, stdin); | ||
| if(!input) return; | ||
| strtok(input, "\n"); | ||
| } | ||
| image im = load_image_color(input, net.w, net.h); | ||
| float *X = im.data; | ||
| float *predictions = network_predict(net, X); | ||
| top_predictions(net, 26, indexes); | ||
| //printf("%s: Predicted in %f seconds.\n", input, sec(clock()-time)); | ||
| for(i = 0; i < 26; ++i){ | ||
| int index = indexes[i]; | ||
| if(i != 0) printf(", "); | ||
| printf("%s %f", names[index], predictions[index]); | ||
| } | ||
| printf("\n"); | ||
| fflush(stdout); | ||
| free_image(im); | ||
| if (filename) break; | ||
| } | ||
| } | ||
|
|
||
| void valid_captcha(char *cfgfile, char *weightfile, char *filename) | ||
| { | ||
| char **labels = get_labels("/data/captcha/reimgs.labels.list"); | ||
| network net = parse_network_cfg(cfgfile); | ||
| if(weightfile){ | ||
| load_weights(&net, weightfile); | ||
| } | ||
| list *plist = get_paths("/data/captcha/reimgs.fg.list"); | ||
| char **paths = (char **)list_to_array(plist); | ||
| int N = plist->size; | ||
| int outputs = net.outputs; | ||
|
|
||
| set_batch_network(&net, 1); | ||
| srand(2222222); | ||
| int i, j; | ||
| for(i = 0; i < N; ++i){ | ||
| if (i%100 == 0) fprintf(stderr, "%d\n", i); | ||
| image im = load_image_color(paths[i], net.w, net.h); | ||
| float *X = im.data; | ||
| float *predictions = network_predict(net, X); | ||
| //printf("%s: Predicted in %f seconds.\n", input, sec(clock()-time)); | ||
| int truth = -1; | ||
| for(j = 0; j < 13; ++j){ | ||
| if (strstr(paths[i], labels[j])) truth = j; | ||
| } | ||
| if (truth == -1){ | ||
| fprintf(stderr, "bad: %s\n", paths[i]); | ||
| return; | ||
| } | ||
| printf("%d, ", truth); | ||
| for(j = 0; j < outputs; ++j){ | ||
| if (j != 0) printf(", "); | ||
| printf("%f", predictions[j]); | ||
| } | ||
| printf("\n"); | ||
| fflush(stdout); | ||
| free_image(im); | ||
| if (filename) break; | ||
| } | ||
| } | ||
|
|
||
| /* | ||
| void train_captcha(char *cfgfile, char *weightfile) | ||
| { | ||
| float avg_loss = -1; | ||
| srand(time(0)); | ||
| char *base = basecfg(cfgfile); | ||
| printf("%s\n", base); | ||
| network net = parse_network_cfg(cfgfile); | ||
| if(weightfile){ | ||
| load_weights(&net, weightfile); | ||
| } | ||
| printf("Learning Rate: %g, Momentum: %g, Decay: %g\n", net.learning_rate, net.momentum, net.decay); | ||
| int imgs = 1024; | ||
| int i = net.seen/imgs; | ||
| list *plist = get_paths("/data/captcha/train.auto5"); | ||
| char **paths = (char **)list_to_array(plist); | ||
| printf("%d\n", plist->size); | ||
| clock_t time; | ||
| while(1){ | ||
| ++i; | ||
| time=clock(); | ||
| data train = load_data_captcha(paths, imgs, plist->size, 10, 200, 60); | ||
| translate_data_rows(train, -128); | ||
| scale_data_rows(train, 1./128); | ||
| printf("Loaded: %lf seconds\n", sec(clock()-time)); | ||
| time=clock(); | ||
| float loss = train_network(net, train); | ||
| net.seen += imgs; | ||
| if(avg_loss == -1) avg_loss = loss; | ||
| avg_loss = avg_loss*.9 + loss*.1; | ||
| printf("%d: %f, %f avg, %lf seconds, %d images\n", i, loss, avg_loss, sec(clock()-time), net.seen); | ||
| free_data(train); | ||
| if(i%10==0){ | ||
| char buff[256]; | ||
| sprintf(buff, "/home/pjreddie/imagenet_backup/%s_%d.weights",base, i); | ||
| save_weights(net, buff); | ||
| } | ||
| } | ||
| } | ||
| void decode_captcha(char *cfgfile, char *weightfile) | ||
| { | ||
| setbuf(stdout, NULL); | ||
| srand(time(0)); | ||
| network net = parse_network_cfg(cfgfile); | ||
| set_batch_network(&net, 1); | ||
| if(weightfile){ | ||
| load_weights(&net, weightfile); | ||
| } | ||
| char filename[256]; | ||
| while(1){ | ||
| printf("Enter filename: "); | ||
| fgets(filename, 256, stdin); | ||
| strtok(filename, "\n"); | ||
| image im = load_image_color(filename, 300, 57); | ||
| scale_image(im, 1./255.); | ||
| float *X = im.data; | ||
| float *predictions = network_predict(net, X); | ||
| image out = float_to_image(300, 57, 1, predictions); | ||
| show_image(out, "decoded"); | ||
| #ifdef OPENCV | ||
| cvWaitKey(0); | ||
| #endif | ||
| free_image(im); | ||
| } | ||
| } | ||
| void encode_captcha(char *cfgfile, char *weightfile) | ||
| { | ||
| float avg_loss = -1; | ||
| srand(time(0)); | ||
| char *base = basecfg(cfgfile); | ||
| printf("%s\n", base); | ||
| network net = parse_network_cfg(cfgfile); | ||
| if(weightfile){ | ||
| load_weights(&net, weightfile); | ||
| } | ||
| printf("Learning Rate: %g, Momentum: %g, Decay: %g\n", net.learning_rate, net.momentum, net.decay); | ||
| int imgs = 1024; | ||
| int i = net.seen/imgs; | ||
| list *plist = get_paths("/data/captcha/encode.list"); | ||
| char **paths = (char **)list_to_array(plist); | ||
| printf("%d\n", plist->size); | ||
| clock_t time; | ||
| while(1){ | ||
| ++i; | ||
| time=clock(); | ||
| data train = load_data_captcha_encode(paths, imgs, plist->size, 300, 57); | ||
| scale_data_rows(train, 1./255); | ||
| printf("Loaded: %lf seconds\n", sec(clock()-time)); | ||
| time=clock(); | ||
| float loss = train_network(net, train); | ||
| net.seen += imgs; | ||
| if(avg_loss == -1) avg_loss = loss; | ||
| avg_loss = avg_loss*.9 + loss*.1; | ||
| printf("%d: %f, %f avg, %lf seconds, %d images\n", i, loss, avg_loss, sec(clock()-time), net.seen); | ||
| free_matrix(train.X); | ||
| if(i%100==0){ | ||
| char buff[256]; | ||
| sprintf(buff, "/home/pjreddie/imagenet_backup/%s_%d.weights",base, i); | ||
| save_weights(net, buff); | ||
| } | ||
| } | ||
| } | ||
| void validate_captcha(char *cfgfile, char *weightfile) | ||
| { | ||
| srand(time(0)); | ||
| char *base = basecfg(cfgfile); | ||
| printf("%s\n", base); | ||
| network net = parse_network_cfg(cfgfile); | ||
| if(weightfile){ | ||
| load_weights(&net, weightfile); | ||
| } | ||
| int numchars = 37; | ||
| list *plist = get_paths("/data/captcha/solved.hard"); | ||
| char **paths = (char **)list_to_array(plist); | ||
| int imgs = plist->size; | ||
| data valid = load_data_captcha(paths, imgs, 0, 10, 200, 60); | ||
| translate_data_rows(valid, -128); | ||
| scale_data_rows(valid, 1./128); | ||
| matrix pred = network_predict_data(net, valid); | ||
| int i, k; | ||
| int correct = 0; | ||
| int total = 0; | ||
| int accuracy = 0; | ||
| for(i = 0; i < imgs; ++i){ | ||
| int allcorrect = 1; | ||
| for(k = 0; k < 10; ++k){ | ||
| char truth = int_to_alphanum(max_index(valid.y.vals[i]+k*numchars, numchars)); | ||
| char prediction = int_to_alphanum(max_index(pred.vals[i]+k*numchars, numchars)); | ||
| if (truth != prediction) allcorrect=0; | ||
| if (truth != '.' && truth == prediction) ++correct; | ||
| if (truth != '.' || truth != prediction) ++total; | ||
| } | ||
| accuracy += allcorrect; | ||
| } | ||
| printf("Word Accuracy: %f, Char Accuracy %f\n", (float)accuracy/imgs, (float)correct/total); | ||
| free_data(valid); | ||
| } | ||
| void test_captcha(char *cfgfile, char *weightfile) | ||
| { | ||
| setbuf(stdout, NULL); | ||
| srand(time(0)); | ||
| //char *base = basecfg(cfgfile); | ||
| //printf("%s\n", base); | ||
| network net = parse_network_cfg(cfgfile); | ||
| set_batch_network(&net, 1); | ||
| if(weightfile){ | ||
| load_weights(&net, weightfile); | ||
| } | ||
| char filename[256]; | ||
| while(1){ | ||
| //printf("Enter filename: "); | ||
| fgets(filename, 256, stdin); | ||
| strtok(filename, "\n"); | ||
| image im = load_image_color(filename, 200, 60); | ||
| translate_image(im, -128); | ||
| scale_image(im, 1/128.); | ||
| float *X = im.data; | ||
| float *predictions = network_predict(net, X); | ||
| print_letters(predictions, 10); | ||
| free_image(im); | ||
| } | ||
| } | ||
| */ | ||
| void run_captcha(int argc, char **argv) | ||
| { | ||
| if(argc < 4){ | ||
| fprintf(stderr, "usage: %s %s [train/test/valid] [cfg] [weights (optional)]\n", argv[0], argv[1]); | ||
| return; | ||
| } | ||
|
|
||
| char *cfg = argv[3]; | ||
| char *weights = (argc > 4) ? argv[4] : 0; | ||
| char *filename = (argc > 5) ? argv[5]: 0; | ||
| if(0==strcmp(argv[2], "train")) train_captcha(cfg, weights); | ||
| else if(0==strcmp(argv[2], "test")) test_captcha(cfg, weights, filename); | ||
| else if(0==strcmp(argv[2], "valid")) valid_captcha(cfg, weights, filename); | ||
| //if(0==strcmp(argv[2], "test")) test_captcha(cfg, weights); | ||
| //else if(0==strcmp(argv[2], "encode")) encode_captcha(cfg, weights); | ||
| //else if(0==strcmp(argv[2], "decode")) decode_captcha(cfg, weights); | ||
| //else if(0==strcmp(argv[2], "valid")) validate_captcha(cfg, weights); | ||
| } | ||
|
|