lsd
#include <math.h>
#include "darknet.h"
slerp
void slerp(float *start, float *end, float s, int n, float *out)
{
float omega = acos(dot_cpu(n, start, 1, end, 1));
float so = sin(omega);
fill_cpu(n, 0, out, 1);
axpy_cpu(n, sin((1-s)*omega)/so, start, 1, out, 1);
axpy_cpu(n, sin(s*omega)/so, end, 1, out, 1);
float mag = mag_array(out, n);
scale_array(out, n, 1./mag);
}
함수 이름: slerp
입력:
start: float 포인터. 시작 벡터를 가리키는 포인터입니다.
end: float 포인터. 끝 벡터를 가리키는 포인터입니다.
s: float 값. 보간 매개변수입니다. [0, 1] 범위의 값으로 설정됩니다.
n: 정수. 벡터의 길이 또는 요소 수입니다.
out: float 포인터. 결과 벡터를 저장할 포인터입니다.
동작:
이 함수는 두 벡터 사이를 구면 보간(spherical interpolation)하여 새로운 벡터를 생성합니다.
시작 벡터(start)와 끝 벡터(end) 사이를 매개변수 s를 사용하여 선형적으로 보간하고, 생성된 보간 벡터를 out에 저장합니다.
설명:
이 함수는 주어진 시작 벡터(start)와 끝 벡터(end) 사이를 구면 보간하여 새로운 벡터를 생성합니다.
먼저, 두 벡터 사이의 각도(omega)를 계산하기 위해 dot_cpu 함수를 사용하여 내적 값을 얻습니다. 그리고 이 각도를 사용하여 사인(sin) 값을 계산합니다.
그 다음, 결과 벡터(out)를 0으로 초기화합니다.
axpy_cpu 함수를 사용하여 보간된 벡터를 계산하여 결과 벡터(out)에 더합니다.
여기서는 시작 벡터(start)와 끝 벡터(end)를 보간 매개변수(s)와 사인 값에 따라 선형적으로 보간하여 계산합니다.
마지막으로, 결과 벡터(out)의 크기를 계산하기 위해 mag_array 함수를 사용합니다.
mag_array 함수는 벡터의 크기 또는 배열의 크기를 반환합니다.
그리고 scale_array 함수를 사용하여 결과 벡터(out)를 이 크기로 나누어 정규화합니다.
random_unit_vector_image
image random_unit_vector_image(int w, int h, int c)
{
image im = make_image(w, h, c);
int i;
for(i = 0; i < im.w*im.h*im.c; ++i){
im.data[i] = rand_normal();
}
float mag = mag_array(im.data, im.w*im.h*im.c);
scale_array(im.data, im.w*im.h*im.c, 1./mag);
return im;
}
함수 이름: random_unit_vector_image
입력:
w: 정수. 생성할 이미지의 너비입니다.
h: 정수. 생성할 이미지의 높이입니다.
c: 정수. 생성할 이미지의 채널 수입니다.
동작:
이 함수는 주어진 너비(w), 높이(h), 채널(c)을 가지는 이미지를 생성합니다.
생성된 이미지는 각 픽셀의 값이 무작위로 선택된 단위 벡터(unit vector)로 초기화됩니다.
설명:
이 함수는 주어진 너비(w), 높이(h), 채널(c)을 가지는 이미지(im)를 생성합니다.
make_image 함수를 사용하여 너비, 높이, 채널에 맞는 이미지 객체를 생성합니다.
그리고 이미지의 각 픽셀을 루프를 통해 순회하면서 rand_normal 함수를 사용하여 무작위 값으로 초기화합니다.
이는 각 픽셀의 값을 무작위로 선택한 값으로 설정하는 것을 의미합니다.
이어서 mag_array 함수를 사용하여 이미지 데이터의 크기를 계산합니다.
mag_array 함수는 이미지 데이터의 크기 또는 벡터의 크기를 반환합니다.
그리고 scale_array 함수를 사용하여 이미지 데이터를 이 크기로 나누어 단위 벡터(unit vector)로 정규화합니다.
scale_array 함수는 배열을 주어진 스케일로 나누는 기능을 수행합니다.
마지막으로, 생성된 이미지(im)를 반환합니다.
inter_dcgan
void inter_dcgan(char *cfgfile, char *weightfile)
{
network *net = load_network(cfgfile, weightfile, 0);
set_batch_network(net, 1);
srand(2222222);
clock_t time;
char buff[256];
char *input = buff;
int i, imlayer = 0;
for (i = 0; i < net->n; ++i) {
if (net->layers[i].out_c == 3) {
imlayer = i;
printf("%d\n", i);
break;
}
}
image start = random_unit_vector_image(net->w, net->h, net->c);
image end = random_unit_vector_image(net->w, net->h, net->c);
image im = make_image(net->w, net->h, net->c);
image orig = copy_image(start);
int c = 0;
int count = 0;
int max_count = 15;
while(1){
++c;
if(count == max_count){
count = 0;
free_image(start);
start = end;
end = random_unit_vector_image(net->w, net->h, net->c);
if(c > 300){
end = orig;
}
if(c>300 + max_count) return;
}
++count;
slerp(start.data, end.data, (float)count / max_count, im.w*im.h*im.c, im.data);
float *X = im.data;
time=clock();
network_predict(net, X);
image out = get_network_image_layer(net, imlayer);
//yuv_to_rgb(out);
normalize_image(out);
printf("%s: Predicted in %f seconds.\n", input, sec(clock()-time));
//char buff[256];
sprintf(buff, "out%05d", c);
save_image(out, "out");
save_image(out, buff);
show_image(out, "out", 0);
}
}
함수 이름: inter_dcgan
입력:
cfgfile: 문자열 포인터. 네트워크의 구성 설정 파일 경로입니다.
weightfile: 문자열 포인터. 네트워크의 가중치 파일 경로입니다.
동작:
이 함수는 주어진 구성 설정 파일(cfgfile)과 가중치 파일(weightfile)을 사용하여 DCGAN(Deep Convolutional Generative Adversarial Network)을 보간(interpolation)합니다.
DCGAN은 이미지 생성을 위한 생성자(generator)와 이미지 식별을 위한 판별자(discriminator)를 포함하는 딥러닝 모델입니다.
이 함수는 두 개의 무작위 단위 벡터로부터 시작과 끝 이미지를 생성하고, 이 두 이미지 사이를 보간하여 중간 이미지를 생성합니다.
설명:
이 함수는 구성 설정 파일(cfgfile)과 가중치 파일(weightfile)을 사용하여 네트워크 객체(net)를 로드합니다.
그리고 set_batch_network 함수를 사용하여 네트워크의 배치 크기를 1로 설정합니다. srand 함수를 사용하여 난수 시드를 설정합니다.
이 함수는 루프를 실행하면서 다음 작업을 반복합니다:
네트워크의 레이어를 순회하면서 출력 채널 수(out_c)가 3인 레이어를 찾습니다. 이 레이어를 이미지 레이어(imlayer)로 설정합니다.
random_unit_vector_image 함수를 사용하여 무작위 단위 벡터를 가지는 시작 이미지(start)와 끝 이미지(end)를 생성합니다.
네트워크의 가로(net->w), 세로(net->h), 채널(net->c)을 크기로 가지는 이미지(im)와 복사된 이미지(orig)를 생성합니다.
카운터 변수(count)가 최대 카운트(max_count)에 도달할 때마다 이미지를 업데이트합니다. 시작 이미지(start)를 해제하고, 시작 이미지(start)에 끝 이미지(end)를 할당합니다. 만약 c가 300을 초과하면 끝 이미지(end)를 원래 이미지(orig)로 설정합니다.
slerp 함수를 사용하여 시작 이미지(start)와 끝 이미지(end) 사이를 보간하여 중간 이미지(im)를 생성합니다.
생성된 이미지(im)를 네트워크를 통해 예측합니다.
get_network_image_layer 함수를 사용하여 예측 결과 중 원하는 레이어(imlayer)의 이미지(out)를 가져옵니다.
normalize_image 함수를 사용하여 이미지(out)를 정규화합니다.
생성된 이미지(out)를 출력하고 "out"이라는 이름으로 저장합니다. 또한 순차적인 번호를 가진 파일 이름(buff)으로 이미지를 저장합니다.
test_dcgan
void test_dcgan(char *cfgfile, char *weightfile)
{
network *net = load_network(cfgfile, weightfile, 0);
set_batch_network(net, 1);
srand(2222222);
clock_t time;
char buff[256];
char *input = buff;
int imlayer = 0;
imlayer = net->n-1;
while(1){
image im = make_image(net->w, net->h, net->c);
int i;
for(i = 0; i < im.w*im.h*im.c; ++i){
im.data[i] = rand_normal();
}
//float mag = mag_array(im.data, im.w*im.h*im.c);
//scale_array(im.data, im.w*im.h*im.c, 1./mag);
float *X = im.data;
time=clock();
network_predict(net, X);
image out = get_network_image_layer(net, imlayer);
//yuv_to_rgb(out);
normalize_image(out);
printf("%s: Predicted in %f seconds.\n", input, sec(clock()-time));
save_image(out, "out");
show_image(out, "out", 0);
free_image(im);
}
}
함수 이름: test_dcgan
입력:
cfgfile: 문자열 포인터. 네트워크의 구성 설정 파일 경로입니다.
weightfile: 문자열 포인터. 네트워크의 가중치 파일 경로입니다.
동작:
이 함수는 주어진 구성 설정 파일(cfgfile)과 가중치 파일(weightfile)을 사용하여 DCGAN(Deep Convolutional Generative Adversarial Network)을 테스트합니다.
DCGAN은 이미지 생성을 위한 생성자(generator)와 이미지 식별을 위한 판별자(discriminator)를 포함하는 딥러닝 모델입니다.
이 함수는 생성자 네트워크를 사용하여 이미지를 생성하고, 생성된 이미지를 출력하고 저장합니다.
설명:
이 함수는 구성 설정 파일(cfgfile)과 가중치 파일(weightfile)을 사용하여 네트워크 객체(net)를 로드합니다.
그리고 set_batch_network 함수를 사용하여 네트워크의 배치 크기를 1로 설정합니다.
srand 함수를 사용하여 난수 시드를 설정합니다.
그 후, 무한 루프를 실행하면서 다음 작업을 반복합니다:
make_image 함수를 사용하여 네트워크의 가로(net->w), 세로(net->h), 채널(net->c)을 크기로 가지는 이미지(im)를 생성합니다.
이미지의 각 픽셀을 rand_normal 함수를 사용하여 무작위로 초기화합니다.
network_predict 함수를 사용하여 생성자 네트워크를 통해 이미지를 예측합니다.
get_network_image_layer 함수를 사용하여 예측 결과 중 원하는 레이어(imlayer)의 이미지(out)를 가져옵니다.
normalize_image 함수를 사용하여 이미지(out)를 정규화합니다.
생성된 이미지(out)를 출력하고 "out"이라는 이름으로 저장합니다.
사용한 이미지(im)를 메모리에서 해제합니다.
set_network_alpha_beta
void set_network_alpha_beta(network *net, float alpha, float beta)
{
int i;
for(i = 0; i < net->n; ++i){
if(net->layers[i].type == SHORTCUT){
net->layers[i].alpha = alpha;
net->layers[i].beta = beta;
}
}
}
함수 이름: set_network_alpha_beta
입력:
net: network 구조체 포인터. 네트워크 객체를 나타냅니다.
alpha: 부동 소수점 값. alpha 매개변수로 사용할 값입니다.
beta: 부동 소수점 값. beta 매개변수로 사용할 값입니다.
동작:
이 함수는 주어진 네트워크 객체(net)의 각 레이어 중 타입이 SHORTCUT인 레이어의 alpha와 beta 값을 설정합니다.
SHORTCUT 레이어는 skip 연결을 나타내며, alpha와 beta는 이러한 skip 연결의 가중치를 조절하는 데 사용됩니다.
설명:
이 함수는 네트워크의 레이어를 반복하면서 각 레이어의 타입을 확인합니다.
만약 레이어의 타입이 SHORTCUT인 경우, 해당 레이어의 alpha와 beta 값을 주어진 alpha와 beta로 설정합니다.
이렇게 함으로써 SHORTCUT 레이어의 가중치를 조절할 수 있습니다.
train_prog
void train_prog(char *cfg, char *weight, char *acfg, char *aweight, int clear, int display, char *train_images, int maxbatch)
{
#ifdef GPU
char *backup_directory = "/home/pjreddie/backup/";
srand(time(0));
char *base = basecfg(cfg);
char *abase = basecfg(acfg);
printf("%s\n", base);
network *gnet = load_network(cfg, weight, clear);
network *anet = load_network(acfg, aweight, clear);
int i, j, k;
layer imlayer = gnet->layers[gnet->n-1];
printf("Learning Rate: %g, Momentum: %g, Decay: %g\n", gnet->learning_rate, gnet->momentum, gnet->decay);
int imgs = gnet->batch*gnet->subdivisions;
i = *gnet->seen/imgs;
data train, buffer;
list *plist = get_paths(train_images);
char **paths = (char **)list_to_array(plist);
load_args args= get_base_args(anet);
args.paths = paths;
args.n = imgs;
args.m = plist->size;
args.d = &buffer;
args.type = CLASSIFICATION_DATA;
args.threads=16;
args.classes = 1;
char *ls[2] = {"imagenet", "zzzzzzzz"};
args.labels = ls;
pthread_t load_thread = load_data_in_thread(args);
clock_t time;
gnet->train = 1;
anet->train = 1;
int x_size = gnet->inputs*gnet->batch;
int y_size = gnet->truths*gnet->batch;
float *imerror = cuda_make_array(0, y_size);
float aloss_avg = -1;
if (maxbatch == 0) maxbatch = gnet->max_batches;
while (get_current_batch(gnet) < maxbatch) {
{
int cb = get_current_batch(gnet);
float alpha = (float) cb / (maxbatch/2);
if(alpha > 1) alpha = 1;
float beta = 1 - alpha;
printf("%f %f\n", alpha, beta);
set_network_alpha_beta(gnet, alpha, beta);
set_network_alpha_beta(anet, beta, alpha);
}
i += 1;
time=clock();
pthread_join(load_thread, 0);
train = buffer;
load_thread = load_data_in_thread(args);
printf("Loaded: %lf seconds\n", sec(clock()-time));
data gen = copy_data(train);
for (j = 0; j < imgs; ++j) {
train.y.vals[j][0] = 1;
gen.y.vals[j][0] = 0;
}
time=clock();
for (j = 0; j < gnet->subdivisions; ++j) {
get_next_batch(train, gnet->batch, j*gnet->batch, gnet->truth, 0);
int z;
for(z = 0; z < x_size; ++z){
gnet->input[z] = rand_normal();
}
/*
for(z = 0; z < gnet->batch; ++z){
float mag = mag_array(gnet->input + z*gnet->inputs, gnet->inputs);
scale_array(gnet->input + z*gnet->inputs, gnet->inputs, 1./mag);
}
*/
*gnet->seen += gnet->batch;
forward_network(gnet);
fill_gpu(imlayer.outputs*imlayer.batch, 0, imerror, 1);
fill_cpu(anet->truths*anet->batch, 1, anet->truth, 1);
copy_cpu(anet->inputs*anet->batch, imlayer.output, 1, anet->input, 1);
anet->delta_gpu = imerror;
forward_network(anet);
backward_network(anet);
//float genaloss = *anet->cost / anet->batch;
scal_gpu(imlayer.outputs*imlayer.batch, 1, imerror, 1);
scal_gpu(imlayer.outputs*imlayer.batch, 0, gnet->layers[gnet->n-1].delta_gpu, 1);
axpy_gpu(imlayer.outputs*imlayer.batch, 1, imerror, 1, gnet->layers[gnet->n-1].delta_gpu, 1);
backward_network(gnet);
for(k = 0; k < gnet->batch; ++k){
int index = j*gnet->batch + k;
copy_cpu(gnet->outputs, gnet->output + k*gnet->outputs, 1, gen.X.vals[index], 1);
}
}
harmless_update_network_gpu(anet);
data merge = concat_data(train, gen);
float aloss = train_network(anet, merge);
#ifdef OPENCV
if(display){
image im = float_to_image(anet->w, anet->h, anet->c, gen.X.vals[0]);
image im2 = float_to_image(anet->w, anet->h, anet->c, train.X.vals[0]);
show_image(im, "gen", 1);
show_image(im2, "train", 1);
save_image(im, "gen");
save_image(im2, "train");
}
#endif
update_network_gpu(gnet);
free_data(merge);
free_data(train);
free_data(gen);
if (aloss_avg < 0) aloss_avg = aloss;
aloss_avg = aloss_avg*.9 + aloss*.1;
printf("%d: adv: %f | adv_avg: %f, %f rate, %lf seconds, %d images\n", i, aloss, aloss_avg, get_current_rate(gnet), sec(clock()-time), i*imgs);
if(i%10000==0){
char buff[256];
sprintf(buff, "%s/%s_%d.weights", backup_directory, base, i);
save_weights(gnet, buff);
sprintf(buff, "%s/%s_%d.weights", backup_directory, abase, i);
save_weights(anet, buff);
}
if(i%1000==0){
char buff[256];
sprintf(buff, "%s/%s.backup", backup_directory, base);
save_weights(gnet, buff);
sprintf(buff, "%s/%s.backup", backup_directory, abase);
save_weights(anet, buff);
}
}
char buff[256];
sprintf(buff, "%s/%s_final.weights", backup_directory, base);
save_weights(gnet, buff);
#endif
}
함수 이름: train_prog
입력:
cfg: 문자열 포인터. GAN 네트워크의 설정 파일 경로.
weight: 문자열 포인터. 사전 학습된 GAN 네트워크의 가중치 파일 경로.
acfg: 문자열 포인터. 판별자(Discriminator) 네트워크의 설정 파일 경로.
aweight: 문자열 포인터. 사전 학습된 판별자(Discriminator) 네트워크의 가중치 파일 경로.
clear: 정수. 학습 전 네트워크를 초기화할지 여부를 나타내는 플래그. 1로 설정하면 초기화됩니다.
display: 정수. 학습 중 생성된 이미지를 표시할지 여부를 나타내는 플래그. 1로 설정하면 표시됩니다.
train_images: 문자열 포인터. 학습에 사용할 이미지 데이터의 경로.
maxbatch: 정수. 최대 배치 수.
동작:
이 함수는 Deep Convolutional GAN(DCGAN)을 학습하는 역할을 수행합니다.
입력으로 주어진 설정 파일과 가중치 파일을 사용하여 GAN 및 판별자 네트워크를 로드합니다.
학습 이미지 데이터를 로드하고, 네트워크를 초기화한 후 학습을 시작합니다. 학습은 주어진 최대 배치 수(maxbatch)에 도달할 때까지 반복됩니다.
각 배치에서는 생성자(Generator)와 판별자(Discriminator) 네트워크를 번갈아가며 업데이트하고, 오차를 계산하여 학습합니다.
학습 중에는 생성된 이미지를 표시하고, 일정 주기마다 가중치를 저장합니다.
설명:
이 함수는 주로 GPU를 사용하는 경우를 가정하고 작성되었습니다.
GPU 지원을 사용할 수 없는 경우 해당 부분은 실행되지 않을 수 있습니다.
또한, 학습 중 생성된 이미지를 표시하려면 OPENCV가 필요합니다.
train_dcgan
void train_dcgan(char *cfg, char *weight, char *acfg, char *aweight, int clear, int display, char *train_images, int maxbatch)
{
#ifdef GPU
char *backup_directory = "/home/pjreddie/backup/";
srand(time(0));
char *base = basecfg(cfg);
char *abase = basecfg(acfg);
printf("%s\n", base);
network *gnet = load_network(cfg, weight, clear);
network *anet = load_network(acfg, aweight, clear);
//float orig_rate = anet->learning_rate;
int i, j, k;
layer imlayer = {0};
for (i = 0; i < gnet->n; ++i) {
if (gnet->layers[i].out_c == 3) {
imlayer = gnet->layers[i];
break;
}
}
printf("Learning Rate: %g, Momentum: %g, Decay: %g\n", gnet->learning_rate, gnet->momentum, gnet->decay);
int imgs = gnet->batch*gnet->subdivisions;
i = *gnet->seen/imgs;
data train, buffer;
list *plist = get_paths(train_images);
//int N = plist->size;
char **paths = (char **)list_to_array(plist);
load_args args= get_base_args(anet);
args.paths = paths;
args.n = imgs;
args.m = plist->size;
args.d = &buffer;
args.type = CLASSIFICATION_DATA;
args.threads=16;
args.classes = 1;
char *ls[2] = {"imagenet", "zzzzzzzz"};
args.labels = ls;
pthread_t load_thread = load_data_in_thread(args);
clock_t time;
gnet->train = 1;
anet->train = 1;
int x_size = gnet->inputs*gnet->batch;
int y_size = gnet->truths*gnet->batch;
float *imerror = cuda_make_array(0, y_size);
//int ay_size = anet->truths*anet->batch;
float aloss_avg = -1;
//data generated = copy_data(train);
if (maxbatch == 0) maxbatch = gnet->max_batches;
while (get_current_batch(gnet) < maxbatch) {
i += 1;
time=clock();
pthread_join(load_thread, 0);
train = buffer;
//translate_data_rows(train, -.5);
//scale_data_rows(train, 2);
load_thread = load_data_in_thread(args);
printf("Loaded: %lf seconds\n", sec(clock()-time));
data gen = copy_data(train);
for (j = 0; j < imgs; ++j) {
train.y.vals[j][0] = 1;
gen.y.vals[j][0] = 0;
}
time=clock();
for(j = 0; j < gnet->subdivisions; ++j){
get_next_batch(train, gnet->batch, j*gnet->batch, gnet->truth, 0);
int z;
for(z = 0; z < x_size; ++z){
gnet->input[z] = rand_normal();
}
for(z = 0; z < gnet->batch; ++z){
float mag = mag_array(gnet->input + z*gnet->inputs, gnet->inputs);
scale_array(gnet->input + z*gnet->inputs, gnet->inputs, 1./mag);
}
/*
for(z = 0; z < 100; ++z){
printf("%f, ", gnet->input[z]);
}
printf("\n");
printf("input: %f %f\n", mean_array(gnet->input, x_size), variance_array(gnet->input, x_size));
*/
//cuda_push_array(gnet->input_gpu, gnet->input, x_size);
//cuda_push_array(gnet->truth_gpu, gnet->truth, y_size);
*gnet->seen += gnet->batch;
forward_network(gnet);
fill_gpu(imlayer.outputs*imlayer.batch, 0, imerror, 1);
fill_cpu(anet->truths*anet->batch, 1, anet->truth, 1);
copy_cpu(anet->inputs*anet->batch, imlayer.output, 1, anet->input, 1);
anet->delta_gpu = imerror;
forward_network(anet);
backward_network(anet);
//float genaloss = *anet->cost / anet->batch;
//printf("%f\n", genaloss);
scal_gpu(imlayer.outputs*imlayer.batch, 1, imerror, 1);
scal_gpu(imlayer.outputs*imlayer.batch, 0, gnet->layers[gnet->n-1].delta_gpu, 1);
//printf("realness %f\n", cuda_mag_array(imerror, imlayer.outputs*imlayer.batch));
//printf("features %f\n", cuda_mag_array(gnet->layers[gnet->n-1].delta_gpu, imlayer.outputs*imlayer.batch));
axpy_gpu(imlayer.outputs*imlayer.batch, 1, imerror, 1, gnet->layers[gnet->n-1].delta_gpu, 1);
backward_network(gnet);
/*
for(k = 0; k < gnet->n; ++k){
layer l = gnet->layers[k];
cuda_pull_array(l.output_gpu, l.output, l.outputs*l.batch);
printf("%d: %f %f\n", k, mean_array(l.output, l.outputs*l.batch), variance_array(l.output, l.outputs*l.batch));
}
*/
for(k = 0; k < gnet->batch; ++k){
int index = j*gnet->batch + k;
copy_cpu(gnet->outputs, gnet->output + k*gnet->outputs, 1, gen.X.vals[index], 1);
}
}
harmless_update_network_gpu(anet);
data merge = concat_data(train, gen);
//randomize_data(merge);
float aloss = train_network(anet, merge);
//translate_image(im, 1);
//scale_image(im, .5);
//translate_image(im2, 1);
//scale_image(im2, .5);
#ifdef OPENCV
if(display){
image im = float_to_image(anet->w, anet->h, anet->c, gen.X.vals[0]);
image im2 = float_to_image(anet->w, anet->h, anet->c, train.X.vals[0]);
show_image(im, "gen", 1);
show_image(im2, "train", 1);
save_image(im, "gen");
save_image(im2, "train");
}
#endif
/*
if(aloss < .1){
anet->learning_rate = 0;
} else if (aloss > .3){
anet->learning_rate = orig_rate;
}
*/
update_network_gpu(gnet);
free_data(merge);
free_data(train);
free_data(gen);
if (aloss_avg < 0) aloss_avg = aloss;
aloss_avg = aloss_avg*.9 + aloss*.1;
printf("%d: adv: %f | adv_avg: %f, %f rate, %lf seconds, %d images\n", i, aloss, aloss_avg, get_current_rate(gnet), sec(clock()-time), i*imgs);
if(i%10000==0){
char buff[256];
sprintf(buff, "%s/%s_%d.weights", backup_directory, base, i);
save_weights(gnet, buff);
sprintf(buff, "%s/%s_%d.weights", backup_directory, abase, i);
save_weights(anet, buff);
}
if(i%1000==0){
char buff[256];
sprintf(buff, "%s/%s.backup", backup_directory, base);
save_weights(gnet, buff);
sprintf(buff, "%s/%s.backup", backup_directory, abase);
save_weights(anet, buff);
}
}
char buff[256];
sprintf(buff, "%s/%s_final.weights", backup_directory, base);
save_weights(gnet, buff);
#endif
}
함수 이름: train_dcgan
입력:
cfg: DCGAN의 구성 파일 경로 (문자열)
weight: 사전 학습된 DCGAN 모델의 가중치 파일 경로 (문자열)
acfg: Adversarial Network(경쟁 신경망)의 구성 파일 경로 (문자열)
aweight: 사전 학습된 Adversarial Network 모델의 가중치 파일 경로 (문자열)
clear: 가중치 초기화 여부 (정수, 0 또는 1)
display: 학습 과정에서 이미지를 표시할지 여부 (정수, 0 또는 1)
train_images: 학습에 사용할 이미지 경로가 포함된 파일의 경로 (문자열)
maxbatch: 최대 배치 수 (정수)
동작:
DCGAN 및 Adversarial Network을 사용하여 모델을 학습하는 함수입니다. GPU를 사용할 때만 동작합니다.
설명:
주어진 경로로부터 DCGAN 및 Adversarial Network 모델을 로드합니다.
이미지 처리를 위한 레이어를 찾고 초기화 작업을 수행합니다.
학습 이미지를 로드하고 데이터를 처리하기 위한 인자를 설정합니다.
데이터를 비동기적으로 로드하고, DCGAN과 Adversarial Network를 학습합니다.
학습 진행 상황을 출력하고, 주기적으로 모델 가중치를 저장합니다.
학습이 완료되면 최종 모델 가중치를 저장합니다.
학습 과정에서 display 옵션이 활성화된 경우 이미지를 표시하고 저장합니다.
train_colorizer
void train_colorizer(char *cfg, char *weight, char *acfg, char *aweight, int clear, int display)
{
#ifdef GPU
//char *train_images = "/home/pjreddie/data/coco/train1.txt";
//char *train_images = "/home/pjreddie/data/coco/trainvalno5k.txt";
char *train_images = "/home/pjreddie/data/imagenet/imagenet1k.train.list";
char *backup_directory = "/home/pjreddie/backup/";
srand(time(0));
char *base = basecfg(cfg);
char *abase = basecfg(acfg);
printf("%s\n", base);
network *net = load_network(cfg, weight, clear);
network *anet = load_network(acfg, aweight, clear);
int i, j, k;
layer imlayer = {0};
for (i = 0; i < net->n; ++i) {
if (net->layers[i].out_c == 3) {
imlayer = net->layers[i];
break;
}
}
printf("Learning Rate: %g, Momentum: %g, Decay: %g\n", net->learning_rate, net->momentum, net->decay);
int imgs = net->batch*net->subdivisions;
i = *net->seen/imgs;
data train, buffer;
list *plist = get_paths(train_images);
//int N = plist->size;
char **paths = (char **)list_to_array(plist);
load_args args= get_base_args(net);
args.paths = paths;
args.n = imgs;
args.m = plist->size;
args.d = &buffer;
args.type = CLASSIFICATION_DATA;
args.classes = 1;
char *ls[2] = {"imagenet"};
args.labels = ls;
pthread_t load_thread = load_data_in_thread(args);
clock_t time;
int x_size = net->inputs*net->batch;
//int y_size = x_size;
net->delta = 0;
net->train = 1;
float *pixs = calloc(x_size, sizeof(float));
float *graypixs = calloc(x_size, sizeof(float));
//float *y = calloc(y_size, sizeof(float));
//int ay_size = anet->outputs*anet->batch;
anet->delta = 0;
anet->train = 1;
float *imerror = cuda_make_array(0, imlayer.outputs*imlayer.batch);
float aloss_avg = -1;
float gloss_avg = -1;
//data generated = copy_data(train);
while (get_current_batch(net) < net->max_batches) {
i += 1;
time=clock();
pthread_join(load_thread, 0);
train = buffer;
load_thread = load_data_in_thread(args);
printf("Loaded: %lf seconds\n", sec(clock()-time));
data gray = copy_data(train);
for(j = 0; j < imgs; ++j){
image gim = float_to_image(net->w, net->h, net->c, gray.X.vals[j]);
grayscale_image_3c(gim);
train.y.vals[j][0] = .95;
gray.y.vals[j][0] = .05;
}
time=clock();
float gloss = 0;
for(j = 0; j < net->subdivisions; ++j){
get_next_batch(train, net->batch, j*net->batch, pixs, 0);
get_next_batch(gray, net->batch, j*net->batch, graypixs, 0);
cuda_push_array(net->input_gpu, graypixs, net->inputs*net->batch);
cuda_push_array(net->truth_gpu, pixs, net->truths*net->batch);
/*
image origi = float_to_image(net->w, net->h, 3, pixs);
image grayi = float_to_image(net->w, net->h, 3, graypixs);
show_image(grayi, "gray");
show_image(origi, "orig");
cvWaitKey(0);
*/
*net->seen += net->batch;
forward_network_gpu(net);
fill_gpu(imlayer.outputs*imlayer.batch, 0, imerror, 1);
copy_gpu(anet->inputs*anet->batch, imlayer.output_gpu, 1, anet->input_gpu, 1);
fill_gpu(anet->inputs*anet->batch, .95, anet->truth_gpu, 1);
anet->delta_gpu = imerror;
forward_network_gpu(anet);
backward_network_gpu(anet);
scal_gpu(imlayer.outputs*imlayer.batch, 1./100., net->layers[net->n-1].delta_gpu, 1);
scal_gpu(imlayer.outputs*imlayer.batch, 1, imerror, 1);
printf("realness %f\n", cuda_mag_array(imerror, imlayer.outputs*imlayer.batch));
printf("features %f\n", cuda_mag_array(net->layers[net->n-1].delta_gpu, imlayer.outputs*imlayer.batch));
axpy_gpu(imlayer.outputs*imlayer.batch, 1, imerror, 1, net->layers[net->n-1].delta_gpu, 1);
backward_network_gpu(net);
gloss += *net->cost /(net->subdivisions*net->batch);
for(k = 0; k < net->batch; ++k){
int index = j*net->batch + k;
copy_cpu(imlayer.outputs, imlayer.output + k*imlayer.outputs, 1, gray.X.vals[index], 1);
}
}
harmless_update_network_gpu(anet);
data merge = concat_data(train, gray);
//randomize_data(merge);
float aloss = train_network(anet, merge);
update_network_gpu(net);
#ifdef OPENCV
if(display){
image im = float_to_image(anet->w, anet->h, anet->c, gray.X.vals[0]);
image im2 = float_to_image(anet->w, anet->h, anet->c, train.X.vals[0]);
show_image(im, "gen", 1);
show_image(im2, "train", 1);
}
#endif
free_data(merge);
free_data(train);
free_data(gray);
if (aloss_avg < 0) aloss_avg = aloss;
aloss_avg = aloss_avg*.9 + aloss*.1;
gloss_avg = gloss_avg*.9 + gloss*.1;
printf("%d: gen: %f, adv: %f | gen_avg: %f, adv_avg: %f, %f rate, %lf seconds, %d images\n", i, gloss, aloss, gloss_avg, aloss_avg, get_current_rate(net), sec(clock()-time), i*imgs);
if(i%1000==0){
char buff[256];
sprintf(buff, "%s/%s_%d.weights", backup_directory, base, i);
save_weights(net, buff);
sprintf(buff, "%s/%s_%d.weights", backup_directory, abase, i);
save_weights(anet, buff);
}
if(i%100==0){
char buff[256];
sprintf(buff, "%s/%s.backup", backup_directory, base);
save_weights(net, buff);
sprintf(buff, "%s/%s.backup", backup_directory, abase);
save_weights(anet, buff);
}
}
char buff[256];
sprintf(buff, "%s/%s_final.weights", backup_directory, base);
save_weights(net, buff);
#endif
}
함수 이름: train_colorizer
입력:
char *cfg: 컬러라이저(Colorizer) 모델의 설정 파일 경로
char *weight: 컬러라이저 모델의 가중치 파일 경로
char *acfg: 컨디셔널(Conditional) 모델의 설정 파일 경로
char *aweight: 컨디셔널 모델의 가중치 파일 경로
int clear: 가중치 초기화 여부를 나타내는 플래그
int display: 중간 과정을 화면에 표시할지 여부를 나타내는 플래그
동작:
주어진 설정과 가중치를 사용하여 컬러라이저(Colorizer) 모델과 컨디셔널(Conditional) 모델을 로드한다.
학습 데이터를 로드하고 전처리 작업을 수행한다.
컬러 이미지와 흑백 이미지를 생성하고, 컨디셔널 모델의 학습을 진행한다.
컬러라이저 모델을 업데이트하고, 중간 결과를 화면에 표시한다.
주기적으로 가중치를 백업하고 저장한다.
설명:
이 함수는 컬러라이저(Colorizer) 모델을 학습시키는 함수이다.
주어진 설정 파일과 가중치 파일을 사용하여 컬러라이저 모델과 컨디셔널 모델을 로드한다.
학습 데이터를 로드하기 위해 경로 및 데이터 관련 설정을 초기화한다.
데이터를 로드하는 스레드를 시작하고, 로드 완료까지 대기한다.
로드된 데이터를 기반으로 흑백 이미지를 생성하고, 컨디셔널 모델의 입력으로 사용한다.
컬러라이저 모델을 업데이트하고, 중간 결과를 화면에 표시한다(OpenCV 사용).
학습 중에는 주기적으로 가중치를 백업하고 저장한다.
학습이 완료되면 최종 가중치를 저장한다.
주요한 변수와 동작은 다음과 같다:
cfg: 컬러라이저(Colorizer) 모델의 설정 파일 경로
weight: 컬러라이저 모델의 가중치 파일 경로
acfg: 컨디셔널(Conditional) 모델의 설정 파일 경로
aweight: 컨디셔널 모델의 가중치 파일 경로
clear: 가중치 초기화 여부를 나타내는 플래그
display: 중간 과정을 화면에 표시할지 여부를 나타내는 플래그
test_lsd
void test_lsd(char *cfg, char *weights, char *filename, int gray)
{
network *net = load_network(cfg, weights, 0);
set_batch_network(net, 1);
srand(2222222);
clock_t time;
char buff[256];
char *input = buff;
int i, imlayer = 0;
for (i = 0; i < net->n; ++i) {
if (net->layers[i].out_c == 3) {
imlayer = i;
printf("%d\n", i);
break;
}
}
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, 0, 0);
image resized = resize_min(im, net->w);
image crop = crop_image(resized, (resized.w - net->w)/2, (resized.h - net->h)/2, net->w, net->h);
if(gray) grayscale_image_3c(crop);
float *X = crop.data;
time=clock();
network_predict(net, X);
image out = get_network_image_layer(net, imlayer);
//yuv_to_rgb(out);
constrain_image(out);
printf("%s: Predicted in %f seconds.\n", input, sec(clock()-time));
save_image(out, "out");
show_image(out, "out", 1);
show_image(crop, "crop", 0);
free_image(im);
free_image(resized);
free_image(crop);
if (filename) break;
}
}
함수 이름: test_lsd
입력:
char *cfg: LSD 테스트에 사용되는 설정 파일 경로
char *weights: LSD 테스트에 사용되는 가중치 파일 경로
char *filename: 테스트할 이미지 파일 경로
int gray: 그레이스케일 이미지로 변환할지 여부를 나타내는 플래그
동작:
주어진 설정과 가중치를 사용하여 LSD (Line Segment Detection) 모델을 로드한다.
LSD 모델에 대해 테스트 이미지를 입력으로 전달하고 예측 결과를 얻는다.
예측 결과를 가공하여 출력하고, 결과 이미지를 저장하고 표시한다.
설명:
이 함수는 LSD (Line Segment Detection) 모델을 테스트하는 함수이다.
주어진 설정 파일과 가중치 파일을 사용하여 LSD 모델을 로드한다.
테스트할 이미지 파일의 경로를 입력으로 받는다. 그렇지 않은 경우 사용자로부터 경로를 입력받는다.
테스트 이미지를 로드하고, 크기를 조정하고, 필요에 따라 그레이스케일로 변환한다.
변환된 이미지를 LSD 모델에 입력으로 전달하여 예측 결과를 얻는다.
예측 결과를 출력하고, 결과 이미지를 저장하고 표시한다.
테스트 작업을 반복하여 여러 이미지에 대해 테스트할 수 있다.
주요한 변수와 동작은 다음과 같다:
cfg: LSD 테스트에 사용되는 설정 파일 경로
weights: LSD 테스트에 사용되는 가중치 파일 경로
filename: 테스트할 이미지 파일 경로
gray: 그레이스케일 이미지로 변환할지 여부를 나타내는 플래그
imlayer: 출력 이미지를 가져올 레이어 인덱스
입력된 이미지 파일의 경로를 확인하고, 존재하는 경우 해당 경로를 입력으로 사용한다.
존재하지 않는 경우 사용자로부터 이미지 파일 경로를 입력받는다.
이미지 파일을 로드하고, 크기를 조정하고, 필요에 따라 그레이스케일로 변환한다.
변환된 이미지를 LSD 모델에 입력으로 전달하여 예측 결과를 얻는다.
결과 이미지를 출력하고, 저장한다.
테스트 작업을 반복하여 다른 이미지에 대해 테스트할 수 있다.
run_lsd
void run_lsd(int argc, char **argv)
{
if(argc < 4){
fprintf(stderr, "usage: %s %s [train/test/valid] [cfg] [weights (optional)]\n", argv[0], argv[1]);
return;
}
int clear = find_arg(argc, argv, "-clear");
int display = find_arg(argc, argv, "-display");
int batches = find_int_arg(argc, argv, "-b", 0);
char *file = find_char_arg(argc, argv, "-file", "/home/pjreddie/data/imagenet/imagenet1k.train.list");
char *cfg = argv[3];
char *weights = (argc > 4) ? argv[4] : 0;
char *filename = (argc > 5) ? argv[5] : 0;
char *acfg = argv[5];
char *aweights = (argc > 6) ? argv[6] : 0;
//if(0==strcmp(argv[2], "train")) train_lsd(cfg, weights, clear);
//else if(0==strcmp(argv[2], "train2")) train_lsd2(cfg, weights, acfg, aweights, clear);
//else if(0==strcmp(argv[2], "traincolor")) train_colorizer(cfg, weights, acfg, aweights, clear);
//else if(0==strcmp(argv[2], "train3")) train_lsd3(argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], clear);
if(0==strcmp(argv[2], "traingan")) train_dcgan(cfg, weights, acfg, aweights, clear, display, file, batches);
else if(0==strcmp(argv[2], "trainprog")) train_prog(cfg, weights, acfg, aweights, clear, display, file, batches);
else if(0==strcmp(argv[2], "traincolor")) train_colorizer(cfg, weights, acfg, aweights, clear, display);
else if(0==strcmp(argv[2], "gan")) test_dcgan(cfg, weights);
else if(0==strcmp(argv[2], "inter")) inter_dcgan(cfg, weights);
else if(0==strcmp(argv[2], "test")) test_lsd(cfg, weights, filename, 0);
else if(0==strcmp(argv[2], "color")) test_lsd(cfg, weights, filename, 1);
/*
else if(0==strcmp(argv[2], "valid")) validate_lsd(cfg, weights);
*/
}
함수 이름: run_lsd
입력:
int argc: 프로그램 실행 시 전달되는 명령행 인자의 개수
char **argv: 프로그램 실행 시 전달되는 명령행 인자 배열
동작:
주어진 명령행 인자를 기반으로 LSD (Line Segment Detection) 관련 작업을 실행하는 함수이다.
프로그램 실행 시 필요한 인자의 개수를 체크하고, 부족한 경우 사용법을 출력하고 함수를 종료한다.
다양한 옵션과 함께 LSD 관련 작업을 실행한다.
주어진 명령행 인자를 분석하여 해당하는 작업을 수행한다.
설명:
이 함수는 LSD (Line Segment Detection) 관련 작업을 실행하는 함수이다.
프로그램 실행 시 전달되는 명령행 인자를 기반으로 작업을 결정하고 해당 작업을 수행한다.
프로그램 실행 시 인자의 개수가 충분하지 않은 경우, 즉시 사용법을 출력하고 함수를 종료한다.
주요한 인자와 작업은 다음과 같다:
cfg: LSD 작업에 사용되는 설정 파일 경로
weights: LSD 작업에 사용되는 가중치 파일 경로 (옵션)
filename: 테스트 작업에 사용되는 파일 경로 (옵션)
acfg: 다른 네트워크의 설정 파일 경로 (옵션)
aweights: 다른 네트워크의 가중치 파일 경로 (옵션)
clear: 작업 실행 전에 이전의 데이터를 지울지 여부를 나타내는 플래그
display: 결과를 표시할지 여부를 나타내는 플래그
batches: 배치 크기를 지정하는 정수 값
file: 데이터 파일 경로
주어진 명령행 인자를 분석하여 해당하는 작업을 수행한다.
주석 처리된 코드는 주석을 해제하고 해당하는 함수를 호출하는 부분이다.
주로
train_*
,test_*
등의 함수를 호출하여 LSD 관련 작업을 수행한다.
Last updated
Was this helpful?