태스크
최대 정확도를 갖춘 교육 샘플을 기반으로 음성 샘플 (음성 또는 "속삭임, 또는 속삭임"으로 "예", "예"또는 "아니오"라고 함)의 음성 인식을 수행하는 최소 바이트의 소스 또는 이진 코드로 프로그램을 구현합니다. .
이 프로그램은 읽어야한다 train/yes0.wav
, train/no0.wav
, train/yes1.wav
등 (400 yeses 및 교육 데이터 세트 (400) noes가)에 후 읽기 시작 inputs/0.wav
, inputs/1.wav
그것은 "예"또는 "아니오"(또는 다른 단어를 분석하고 출력 파일을 찾기 위해 실패 할 때까지 중간 답변).
원하는 train/
경우을 읽는 대신 프로그램을 사전 훈련시킬 수 있지만 결과 데이터 테이블은 점수에 포함됩니다 (그리고 훈련 샘플에 과적 합을 조심하십시오-시험과 중복되지 않음). 이 경우 데이터 테이블을 생성하는 데 사용되는 프로그램을 부록으로 포함하는 것이 좋습니다.
모든 샘플 파일은 필터링 / 노이즈 감소없이 랩탑 마이크에서 리틀 엔디안 16 비트 스테레오 WAV 파일입니다.
제한
금지 된 기능 :
- 네트워크 사용;
- 응답 파일에 도달하려고합니다
inputs/key
. runner
정확도를 계산 하는 프로그램을 전복시키는 행위 ;- 기존 인식 라이브러리 사용 FFT 구현으로의 연결은 허용되지 않습니다 : 일정한 양의 정보 (
sin
또는 같은atan2
)를 취하는 외부 수학 함수 만 허용됩니다. FFT를 원한다면 프로그램 소스 코드에 구현을 추가하십시오 (필요한 경우 다국어 가능).
자원 한도 :
- 프로그램은 i5 랩탑에서 30 분 이상의 CPU 시간을 가져서는 안됩니다. 더 많은 시간이 걸리면 처음 30 분 동안 생성 된 출력 만 계산되고 나머지는 반 일치로 간주됩니다.
- 메모리 제한 : 1GB (임시 파일 포함);
도구
tools/runner
프로그램이 자동으로 솔루션을 실행하고 정확도를 계산합니다.
$ tools/runner solutions/example train train/key
Accuracy: 548 ‰
훈련 데이터 또는 실제 시험 데이터를 사용하여 프로그램을 검사 할 수 있습니다. 시험 데이터 세트에 대한 답변을 제출하고 데이터 세트를 공개 할 때까지 결과 (정확도 백분율)를 게시하려고합니다.
채점
정확도에 따라 5 가지 종류의 솔루션이 있습니다.
- 모든 샘플이 올바르게 추측 됨 : 클래스 0;
- 정확도 950-999 : 클래스 1;
- 정확도 835-950 : 클래스 2;
- 정확도 720-834 : 클래스 3;
- 정확도 615-719 : 클래스 4;
각 클래스 내에서 점수는 솔루션이 차지하는 바이트 수입니다.
허용되는 답변 : 비어 있지 않은 최고의 클래스에서 가장 작은 솔루션.
모래밭
- 도구가있는 Github 프로젝트 : https://github.com/vi/codegolf-jein
- 교육 데이터 세트 : http://vi-server.org/pub/codegolf-jein-train.tar.xz
- 검사 데이터 세트는 지금까지 비공개로 유지되며 Github 리포지토리에 사용 가능한 체크섬 (HMAC)이 있습니다.
모든 샘플은 CC-0 (Public Domain), 스크립트 및 프로그램은 MIT로 간주해야합니다.
솔루션 예
인식 품질이 매우 낮고 파일을 읽고 응답을 출력하는 방법 만 보여줍니다.
#define _BSD_SOURCE
#include <stdio.h>
#include <assert.h>
#include <endian.h>
#define Nvols 30
#define BASS_WINDOW 60
#define MID_WINDOW 4
struct training_info {
double bass_volumes[Nvols];
double mid_volumes[Nvols];
double treble_volumes[Nvols];
int n;
};
struct training_info yes;
struct training_info no;
static int __attribute__((const)) mod(int n, int d) {
int m = n % d;
if (m < 0) m+=d;
return m;
}
// harccoded to 2 channel s16le
int get_file_info(const char* name, struct training_info *inf) {
FILE* in = fopen(name, "rb");
if (!in) return -1;
setvbuf(in, NULL, _IOFBF, 65536);
inf->n = 1;
fseek(in, 0, SEEK_END);
long filesize = ftell(in);
fseek(in, 128, SEEK_SET);
filesize -= 128; // exclude header and some initial samples
int nsamples = filesize / 4;
double bass_a=0, mid_a=0;
const int HISTSIZE = 101;
double xhistory[HISTSIZE];
int histpointer=0;
int histsize = 0;
//FILE* out = fopen("debug.raw", "wb");
int i;
for (i=0; i<Nvols; ++i) {
int j;
double total_vol = 0;
double bass_vol = 0;
double mid_vol = 0;
double treble_vol = 0;
for (j=0; j<nsamples / Nvols; ++j) {
signed short int l, r; // a sample
if(fread(&l, 2, 1, in)!=1) break;
if(fread(&r, 2, 1, in)!=1) break;
double x = 1/65536.0 * ( le16toh(l) + le16toh(r) );
bass_a += x;
mid_a += x;
if (histsize == HISTSIZE-1) bass_a -= xhistory[mod(histpointer-BASS_WINDOW,HISTSIZE)];
if (histsize == HISTSIZE-1) mid_a -= xhistory[mod(histpointer-MID_WINDOW ,HISTSIZE)];
double bass = bass_a / BASS_WINDOW;
double mid = mid_a / MID_WINDOW - bass;
double treble = x - mid_a/MID_WINDOW;
xhistory[histpointer++] = x;
if(histpointer>=HISTSIZE) histpointer=0;
if(histsize < HISTSIZE-1) ++histsize;
total_vol += bass*bass + mid*mid + treble*treble;
bass_vol += bass*bass;
mid_vol += mid*mid;
treble_vol += treble*treble;
/*
signed short int y;
y = 65536 * bass;
y = htole16(y);
fwrite(&y, 2, 1, out);
fwrite(&y, 2, 1, out);
*/
}
inf->bass_volumes[i] = bass_vol / total_vol;
inf->mid_volumes[i] = mid_vol / total_vol;
inf->treble_volumes[i] = treble_vol / total_vol;
//fprintf(stderr, "%lf %lf %lf %s\n", inf->bass_volumes[i], inf->mid_volumes[i], inf->treble_volumes[i], name);
}
fclose(in);
return 0;
}
static void zerotrdata(struct training_info *inf) {
int i;
inf->n = 0;
for (i=0; i<Nvols; ++i) {
inf->bass_volumes[i] = 0;
inf->mid_volumes[i] = 0;
inf->treble_volumes[i] = 0;
}
}
static void train1(const char* prefix, struct training_info *inf)
{
char buf[50];
int i;
for(i=0;; ++i) {
sprintf(buf, "%s%d.wav", prefix, i);
struct training_info ti;
if(get_file_info(buf, &ti)) break;
++inf->n;
int j;
for (j=0; j<Nvols; ++j) {
inf->bass_volumes[j] += ti.bass_volumes[j];
inf->mid_volumes[j] += ti.mid_volumes[j];
inf->treble_volumes[j] += ti.treble_volumes[j];
}
}
int j;
for (j=0; j<Nvols; ++j) {
inf->bass_volumes[j] /= inf->n;
inf->mid_volumes[j] /= inf->n;
inf->treble_volumes[j] /= inf->n;
}
}
static void print_part(struct training_info *inf, FILE* f) {
fprintf(f, "%d\n", inf->n);
int j;
for (j=0; j<Nvols; ++j) {
fprintf(f, "%lf %lf %lf\n", inf->bass_volumes[j], inf->mid_volumes[j], inf->treble_volumes[j]);
}
}
static void train() {
zerotrdata(&yes);
zerotrdata(&no);
fprintf(stderr, "Training...\n");
train1("train/yes", &yes);
train1("train/no", &no);
fprintf(stderr, "Training completed.\n");
//print_part(&yes, stderr);
//print_part(&no, stderr);
int j;
for (j=0; j<Nvols; ++j) {
if (yes.bass_volumes[j] > no.bass_volumes[j]) { yes.bass_volumes[j] = 1; no.bass_volumes[j] = 0; }
if (yes.mid_volumes[j] > no.mid_volumes[j]) { yes.mid_volumes[j] = 1; no.mid_volumes[j] = 0; }
if (yes.treble_volumes[j] > no.treble_volumes[j]) { yes.treble_volumes[j] = 1; no.treble_volumes[j] = 0; }
}
}
double delta(struct training_info *t1, struct training_info *t2) {
int j;
double d = 0;
for (j=0; j<Nvols; ++j) {
double rb = t1->bass_volumes[j] - t2->bass_volumes[j];
double rm = t1->mid_volumes[j] - t2->mid_volumes[j];
double rt = t1->treble_volumes[j] - t2->treble_volumes[j];
d += rb*rb + rm*rm + rt*rt;
}
return d;
}
int main(int argc, char* argv[])
{
(void)argc; (void)argv;
train();
int i;
int yes_count = 0;
int no_count = 0;
for (i=0;; ++i) {
char buf[60];
sprintf(buf, "inputs/%d.wav", i);
struct training_info ti;
if(get_file_info(buf, &ti)) break;
double dyes = delta(&yes, &ti);
double dno = delta(&no, &ti);
//printf("%lf %lf %s ", dyes, dno, buf);
if (dyes > dno) {
printf("no\n");
++no_count;
} else {
printf("yes\n");
++yes_count;
}
}
fprintf(stderr, "yeses: %d noes: %d\n", yes_count, no_count);
}
sum
, 아니면 사용해야합니다 foldl (+) 0
(계산식이 아니고 변덕스럽지 않은 폴더 +
)?
sum
있습니다. 그게 당신의 의도가 아닌 것 같아요?