영어가 매우 짧아... 편하게 읽을려고, 구글 번역기를 활용했습니다.
내용을 요약하면:
- 우리가 기계 학습의 기술에 대해 조금 알게되자 마자 우리는 새로운 프레임 워크 부분을 작성하는 것에 대해 더욱 진지하게 생각하게되었습니다.
- 기계 학습 라이브러리 (주로 Deeplearning4J, Brainstorm 및 Tensorflow)의 소스 코드를 읽는 것 외에도 우리는 우리 자신의 프레임 워크가 어떻게 사용되기를 원했는가를 계획했습니다.
- 우리는 모든 것을 검사하고 시각화 할 수 있기를 원했기 때문에 식별자를 사용하여 레지스트리에 액세스하는 글로벌 방식이 필요했습니다.
- 근본적으로 우리가 이용할 수있는 모든 시간을 채우고, 그 다음에는 몇 시간을 다 써 버렸습니다.
- 그것은 확실히 가치가 있었지만, 이제 우리는 일들이 어떻게 저수준에서 작동 하는지를 확실하게 이해하고 있으며, 가장 중요한 것은 우리가 기계 학습 프레임 워크를 실제로 작성했다고 말할 수 있습니다.
TLDR : 2 년 전에 고등학교 논문에 대한 ML 주제를 결정할 때 조언을 구했던 (
원래 스레드 참조), C#/F#에서 (거의) 처음부터 기계 학습 프레임 워크를 작성했습니다. 다른 사람들만큼 많이 할 수는 없지만, 빠르거나 예쁘지는 않습니다.하지만 우리는 여전히 멋지다고 생각합니다. 여기에 우리의
github repo와 간단한
UI 데모가 있습니다.
결과
우리의 프레임 워크(
Sigma)의 현재 기능 세트를 앞에서 살펴보면 다음 몇 단락에 대한 아이디어를 얻을 수 있습니다.
- 입력, 출력, 밀도, 드롭 아웃, 반복, SoftmaxCE / SquaredDiff 비용 계층
- 그라디언트 디센트, 모멘텀, Adadelta, Adagrad 옵티 마이저
- 체크 포인트의 저장 / 복원, 시간 측정, 특정 기준에 대한 중지 (또는 다른 일을하는 것), 런타임 메트릭스 계산 및보고를위한 후크
- 기능적 자동 차별화 기능으로 새로운 레이어의 쉬운 추가
- 임의로 연결된 구성이 있는 선형 및 비선형 네트워크
- 분산 멀티 및 단일 CPU 및 GPU (CUDA) 백엔드
- 매개 변수를 실시간으로 상호 작용 및 모니터링 할 수있는 기본 그래픽 인터페이스
1. Introduction
이것은 고등학교 논문을 위한 기계 학습 프레임 워크, 우리가 배운 것, 그리고 처음부터 어떻게 쓰는지에 대한 기계 학습 프레임 워크를 작성한 이야기입니다. 이야기는 약 3년 전 시작됩니다: 우리는 MarI/O 라는 슈퍼 마리오 AI의 비디오를 보고 슈퍼 마리오 레벨을 배우는 법을 배웠습니다. 우리는 이것이 모든 시간 중 가장 멋진 것 임을 알았고 고등학교 논문에 대해 적어도 비슷한것을 하고 싶다고 생각했습니다.
1.1 The Original Plan
2 년 전 우리는 고등학교 졸업 논문(원래 스레드 참조)을 위해 실현 가능한 기계 학습 프로젝트의 종류를 결정하는데 도움을 요청했습니다. 꽤 야심 차게, 우리는 약 1000 시간의 시간 투자를 제안했습니다(8 개월 동안 500 시간 씩). 우리는 아직 어떤 프로젝트에 대해 알지 못했습니다. 그 스레드에서, 우리는 관대하게 많은 도움을 받았습니다. 조언은 기존의 논문을 재현하는 것부터 특정 사물을 구현하는 것, 자료를 이해하는 것, 그리고 우리의 관심을 득점한 것을 보는 것에 이르기까지 다양했습니다. 약간 고려한 후에, 우리는 DeepMinds 아케이드 게임 AI의 라인을 따라 뭔가를 구현한 것이 더 일반적인 것으로 생각했습니다. 어떤 이유로 든 쉽게 될 것이라고 생각했습니다. 우리 프로젝트를 좀 더 자세히 계획 할 때, 우리는
- 우리가 무엇을하고 있는지 전혀 몰랐다는 것을 깨달았습니다.
- 모든 일을 처음부터 끝까지 임의로 특정하게 정의하는 것은 애석한 일 입니다.
1.2 Pivoting
매우 생산적인 일을 하기 전에 기계 학습을 올바르게 공부 해야 했습니다. 우리는 이것이 시간이 좀 걸릴 것이라고 생각하고 논문의 이론적 부분을 쓰는데 시간의 일부를 할당했습니다. 그러나 그 당시 우리는 논문의 공식 표적 정의를 제출해야했기 때문에 가장 일반적인 "목표"를 정했습니다. 참고로, 수개월에 걸친 프로젝트에서 우리 프로젝트는 공식적으로 "Software framework for diverse machine learning tasks"라는 이름이 붙여졌습니다. 더 많은 연구와 우리 프로젝트의 실제 목표 정의 초안을 만들려고 시도하는 동안, 우리의 계획은 점차적으로 "모든 종류의 시각적 인 입력"학습 프레임 워크로 피벗 된 특정 유형의 게임을 실행하기위한 기계 학습 프레임 워크에서 점차적으로 "마지막으로"모든 것 "기계 학습 프레임 워크로 이동했습니다. 왜냐하면 왜 그렇게 흥미로운 도전이 아닌 것처럼 보였고 우리는 얼마나 멀리 우리가 얻을 수 있는지 궁금해했습니다.
2. Research and Planning
자, 이제 우리는 기계 학습 프레임 워크를 작성하기로 결정했습니다. 기계 학습 프레임 워크를 만드는 방법은 무엇입니까? 특정 프레임 워크를 사용하는 데 합리적으로 익숙해 지려면 많은 시간이 걸리고, 적절한 가이드, 비디오 자습서 및 포럼을 통해 도움을 요청하는 데는 많은 시간이 걸립니다. 기계 학습 프레임 워크를 작성하는 것은 전혀 다른 이야기이며 따라야 할 12 단계 지침은 없습니다. 상당 기간 동안 우리는 실제로 구현해야하는 부분을 잃었습니다. 끊임없이 새롭고 상충되는 용어, 정의 및 그다지 명백하지 않은 "실제적인 결론은 명백한"조항에 직면합니다. 한 달 조금 넘은 후에 우리는이 기계 학습이 어떻게 작동했는지에 대한 기본적인 이해를 천천히 가졌습니다. - 일반적으로 차별화를 사용하여 단계의 특정 지점에서 근사화 된 함수가있는 함수로 일부 지표가 내려갑니다. - 여전히 마술이지만 조금 덜합니다. (CNN, LSTM, GAN에 대해 읽을 때까지, 우리 각자가 우리를 잠시 혼란스럽게 만들었습니다).
2.1 Sketching our Framework
우리가 기계 학습의 기술에 대해 조금 알게되자 마자 우리는 새로운 프레임 워크 부분을 작성하는 것에 대해 더욱 진지하게 생각하게되었습니다. 이를위한 가이드가 없으므로 우리는 기존 프레임 워크의 소스 코드를 읽는 것에 의지했습니다. - 우리에게 관련있는 부분, 여러 번, 그것이 의미가있을 때 까지, 그 동안 C#을 기본 언어로 사용하기로 결정했습니다. - 주로 우리가 이미 그 언어에 매우 익숙하고 새로운 언어를 배우고 싶지 않기 때문에, 그러나 .NET 을 위한 다른 적절한 신경망 프레임 워크가 없었기 때문에 공식적으로도 그렇습니다. 기계 학습 라이브러리 (주로 Deeplearning4J, Brainstorm 및 Tensorflow)의 소스 코드를 읽는 것 외에도 우리는 우리 자신의 프레임 워크가 어떻게 사용되기를 원했는가를 계획했습니다. 얼마 후, 우리는 외부인으로서 기계 학습 프레임 워크를 알게 될 때 불필요한 혼동이 있었던 것처럼 느꼈고,이를 피하기 위해 API를 설계 하려고 했습니다. 우리의 디자인이 우리에게 의미가 있기 때문에 다른 사람들에게 기존의 것보다 더 합리적이라는 것을 의미하지 않으며, 기계 학습을 사용하여 모두가 자신의 프레임 워크를 작성하여 자신의 온기를 보전하기를 권장합니다.
기계 학습 방법에 대한 우리의 단순한 아이디어는 C#/Java 기반 프로그래밍 경험에서 영감을 얻었습니다. 몇 주 동안 작성한 코드 예제에서 분명합니다.
Sigma sigma = Sigma.Create("minsttest");
GUIMonitor gui = (GUIMonitor) sigma.AddMonitor(new GUIMonitor("Sigma GUI Demo"));
gui.AddTabs({"Overview", "Data", "Tests"});
sigma.Prepare();
DataSetSource inputSource = new MultiDataSetSource(new FileSource("mnist.inputs"), new CompressedFileSource(new FileSource("mnist.inputs.tar.gz"), new URLSource("http://....url...../mnist.inputs.targ.gz";))); DataSetSource targetSource = new MultiDataSetSource(new FileSource("mnist.targets"), new CompressedFileSource(new FileSource("mnist.targets.tar.gz"), new URLSource("http://....url...../mnist.targets.targ.gz"; [, output: "otherthandefault"]) [, compression: new TarGZUnpacker(), output: "mnist.inputs" , forceUpdate: false])); DataSet data = new DataSet(new ImageRecordReader(inputSource, {28, 28}).Extractor({ALL} => {inputs: {Extractor.BatchSize, 1, 28, 28}}).Preprocess(Normalisor()), new StringRecordReader(targetSource).Extractor({0} => {targets: {Extractor.BatchSize, 1}} [, blockSize: auto/all/1024^3]);
Network network = new Network("mynetwork");
network.Architecture = Input(inputShape: {28, 28}) + 2 * FullyConnected(size: 1024) + SoftmaxCE() + Loss();
Trainer trainer = sigma.CreateTrainer("mytrainer");
trainer.SetNetwork(network);
trainer.SetInitialiser(new GaussianInitialiser(mean: 0.0, standardDeviation: 0.05));
trainer.SetTrainingDataIterator(MinibatchIterator(batchSize: 50, data["inputs"], data["targets"]);
trainer.SetOptimiser(new SGDOptimiser(learningRate: 0.01);
trainer.AddActiveHook(EarlyStopper(patience: 3));
trainer.AddActiveHook(StopAfterEpoch(epoch: 2000));
gui.AccentColor["trainer1"] = Colors.DeepOrange;
gui.tabs["overview"].AddSubWindow(new LineChartWindow(name: "Error", sources: {"*<Trainer>.Training.Error"}) [, x: 1, y: 0, width: 2, height: 1]);
gui.tabs["overview"].AddSubWindow(new LineChartWindow(name: "Accuracy", sources: {"*<Trainer>.Training.Accuracy"}));
sigma.Run();
앞서 건너 뛰는 것은 최종 프레임워크가 우리가 여기서 상상한 것과 매우 유사하다는 점에 유의해야합니다. 단지 몇 가지 구문과 이름을 변경하는 것 만으로도 위의 예는 약 1년 전부터 현재의 프레임워크에서 1:1로 사용할 수 있습니다. 배심원은 그것이 정말로 좋은 디자인인지 또는 정말로 나쁜 디자인 인지에 대한 의견이 아직 남아 있습니다. 또한 레이어 생성자 인수에 대한 python 스타일의 kwargs 표기법을 주의 하십시오. 이 표기법은 곧 C#에서 실제로 컴파일되는 것을 선호하여 폐기되었습니다. 그러나 타임 라인으로 되돌아갑니다.
2.2 The Sigma Architecture
코드 예제를 정의하고 기계 학습 프레임 워크가 필요한 거친 부분을 스케치 한 후 우리는 "Sigma.Core"에 대한이 일반 아키텍처를 핵심 구성 요소로 나누었습니다.
- Util: 주로 지루하고, 글쎄요, 유용성은 물론, 우리 아키텍처의 핵심 부분입니다. 우리는 모든 것을 검사하고 시각화 할 수 있기를 원했기 때문에 식별자를 사용하여 레지스트리에 액세스하는 글로벌 방식이 필요했습니다. 우리의 레지스트리는 기본적으로 더 많은 레지스트리를 포함 할 수있는 문자열 키가있는 사전입니다. 중첩 된 레지스트리는 도트 표기법의 레지스트리 확인자를 사용하여 일부 멋진 와일드 카드 및 태그를 천사 괄호 (예 : "network.layers. * <fullyconnected> weight")와 함께 사용하여 해결할 수 있습니다.
- Data: 다양한 형식으로 데이터를 구성하는 레코드 인 데이터 집합은 파이프, 디스크, 웹 또는 어디서 왔는지를로드, 추출, 준비 및 캐시하여 "블록"으로 사용할 수있게합니다. 이 블록은 압축 된 데이터 세트의 일부이며 많은 개별 레코드로 구성되어 있으며 잠재적으로 매우 큰 데이터 세트를 모두 한 번에 메모리에로드하는 것을 방지하는 데 사용됩니다. 또한 데이터 반복자는 데이터 집합에서 더 큰 블록을 조각으로 조각화 한 다음 모델에 공급합니다.
- Architecture: 레이어 "구조"로 구성된 기계 학습 모델에 대한 추상 정의. 완전히 인스턴스화되기 전에 레이어가 어떻게 보이는지 정의하는 간단한 자리 표시 자 레이어입니다. 이 레이어는 순서에 관계없이 원하는 다른 많은 레이어와 연결할 수 있습니다.
- Layers: 불행히도 신경망으로 시작한 이래로 이름이 붙여졌지만, 이들은 기계 학습 네트워크의 개별 레이어입니다. 메타 매개 변수 (예 : 크기)와 실제 훈련 가능한 매개 변수 (예 : 실제 가중치)를 저장합니다.
- Math: 수학 및 저레벨 계산과 직접 관련이있는 모든 것. 모든 자동 차별화 논리 (적절한 기계 학습을 수행하는 데 매우 필요함)와 데이터를 수정하는 모든 요소는 다양한 백엔드 (예 : 분산 CPU / GPU)에서 처리됩니다. 무엇이든 관련하여 파생 상품 계산을 지원하기 위해 기호 객체를 사용하는 접근 방법을 선택했습니다. 실제 데이터가 숨겨져있는 숫자 또는 배열 객체입니다 (가져올 수 있지만 사본을 통해서만 가능함). 이러한 기호 객체는 실제 데이터 수정을 수행하는 핸들러를 통해 전달됩니다. 이 추상화는 CUDA 스트림을 비동기 적으로 실행하여 원시 데이터가 사용자에게 노출 될 수없는 CUDA 지원을 구현할 때 유용합니다 (호스트 장치 동기화가 매우 느림).
- Training: 실제 교육 과정을 중심으로 많은 하위 구성 요소가있는 가장 큰 구성 요소입니다. 트레이닝 프로세스는 "trainer"에 정의되며 다음을 지정합니다.
- Initialisers, 레지스트리 매개 변수로 모델 매개 변수를 구성하는 방법을 정의합니다. 예를 들어, trainer.addInitialiser ( "layers. *. biases", 새 GaussianInitialiser (0.1, 0.0)); 가우시안 분포가 0.1 (평균 0) 인 "bias"라는 모든 매개 변수를 초기화합니다.
- Modifiers, 이는 가중치를 특정 범위로 클리핑하는 것과 같이 런타임에 매개 변수를 수정합니다.
- Optimisers, 모델에서 학습하는 방식 (예 : 그래디언트 디센트)을 정의합니다. 우리는 주로 신경망을 고려했기 때문에 그라디언트 기반 옵티 마이저 만 구현했지만 인터페이스는 이론적으로 모든 종류의 최적화를 지원합니다.
- Hooks, 특정 시간 단계에서 교육 과정에 "연결"하여 원하는대로 할 수 있습니다. (예 : 시각화 업데이트, 체크 포인트 저장 / 복원, 메트릭 계산 및 기록, 일부 조건이 충족되면 무언가를 수행 (예 : 중지)).
- Operators, 일부 매개 변수에 따라 특정 백엔드 계산 핸들러로이를 실행하는 작업자에게 작업을 위임합니다. 주목할 점은 “ 로벌" 및 "로컬"프로세싱의 차별화입니다. 글로벌은 가장 최근의 글로벌 상태입니다. 이 글로벌 상태는 로컬 작업자가 가져 와서 실제 작업을 수행 한 후 작업자에게 결과를 게시하여 전역 범위로 병합합니다. 글로벌 timestep 이벤트는 모든 로컬 근로자가 timestep에 대한 작업을 제출하여 분산 학습에서보다 세밀한 제어를 가능하게하는 경우에만 이론적으로 배출됩니다.
- Sigma: 시그마 환경 및 트레이너를 만들 수있는 루트 네임 스페이스 환경에는 여러 개의 트레이너가 포함될 수 있습니다. 이 트레이너는 모두 실행되고 지정된 경우 (동시에 하이퍼 매개 변수 검색에 도움이되는 것으로 가정) 동시에 시각화됩니다.
- Monitors: 기술적으로 핵심 프로젝트 외부이지만 여전히 구성 요소입니다. 이러한 모니터는 Sigma 환경에 연결될 수 있으며 위에서 언급 한 레지스트리 항목을 사용하여 해당 환경의 강사에 대한 거의 모든 것을 모니터링 할 수 있습니다. 행동은 한 번만 호출되는 특별한 형태의 후크 인 명령을 사용하여 주입 할 수 있습니다. 이런 식으로 모니터는 시그마 프로젝트의 핵심과 거의 독립적으로 사용될 수 있으며, 그래픽 인터페이스 또는 로컬로 호스팅 된 라이브 웹 사이트와 같이 거의 모든 것이 될 수 있습니다.
3. Implementation
이것이 바로 우리가 구현 한 단계입니다. 우리는 주로 시그마와 함께 작업을 시작했습니다. 코어와 내 파트너는 시각화 인터페이스를 사용하여 몇 개월 동안 공통 인터페이스로 작업하여 최종적으로 개별 부품을 결합하고 라이브 그래픽 인터페이스에서 기적적으로 작업 할 수있게되었습니다. 구현의 세부 사항은 매우 흥미롭고 도전적 이었지만 대부분의 세부 사항은 읽기가 어려웠습니다. 대부분의 경우 작동하지 않았고 뭔가를 고칠 때 다음 단계로 넘어갔습니다. 그렇지 않았습니다.
3.1 Low-level Data and Mathematical Processing
우리가 한 첫 번째 작업은 데이터 "ETL"(변환로드 추출) 파이프 라인을 가동 및 실행하는 것이 었습니다. 주로 다양한 소스에서 데이터를 가져 와서 데이터 세트로로드하고 블록으로 추출했습니다. 그런 다음 수학적 처리 부분에 중점을 둡니다. 수학을 사용하고 파생 상품을 계산하는 것과 관련이 있습니다. 필자는 "DiffSharp"라는 이름의 autodiff를위한 F # 라이브러리에 "SigmaDiff"라는 이름의 기능적 자동 차별화 기능을 기반으로했습니다.이 DiffSharp는 n 차원 배열을 지원하고 성능을 크게 개선하며 버그를 수정하고 동시에 여러 개의 비 글로벌 백엔드, 가변 데이터 형식 및 내가 잊어 버린 몇 가지 추가 정보가 포함되어 있습니다. 작업을 수행하는 구체적인 세부 사항은 매우 흥미롭지 않습니다. 일부 특수한 조합의 작업에서와 같이 역 전파가 작동하지 않기 때문에 많은 글루 코드, 리팩터링 및 심야 버그 추적이 있습니다. 한 가지 기억에 남는 버그는 백엔드 작업을 내 자신의 OpenBLAS 기반 백엔드로 다시 매핑 할 때 행렬 변환이 그 모양을 변경하는 것 이상을한다는 것을 잊었습니다. 일이 제대로 작동하지 않아 디버깅 작업에 몇 주가 걸렸습니다. 큰 레이어 또는 minibatch (duh) 당 1 레코드 이상.
3.2 Performance Optimisations
모든 백엔드 작업과 비교하여 레이어 및 옵티 마이저의 "미들웨어"는 구현하기가 다소 어려웠습니다. 특정 레이어와 옵티 마이저를 만드는 방법에 대한 수 백 가지 자습서와 문서가 있었기 때문에 필자 만의 솔루션에 매핑해야했습니다. 실제로, 그 부분은 기껏해야 몇 주간 걸렸을 지 모르지만, 우리는 단지 수십 가지의 버그와 안정성 문제를 발견했기 때문에 훨씬 더 오래 걸렸습니다. 여기서 흥미 진진한 세부 사항을 건너 뛰고,이 시점에서 프레임 워크의 성능이 상당히 나 빠졌다는 점에 유의해야합니다. 나는 하이 엔드 컴퓨터에 단 몇 개의 고밀도 레이어가있는 100 개의 MNIST 레코드 300ms / 반복을 말하고 있습니다. 이 나쁜 성능은 훈련을 느리게 할뿐 아니라 실제 개발을 상당히 많이 중단 시켰으며 몇 가지 치명적인 버그를 숨기고 합리적인 시간 내에 실제 프레임 워크에서 전체 프레임 워크를 테스트 할 수 없었습니다. 왜 우리는 그저 성능을 고치지 않은 것인지 궁금해 할 수도 있습니다. 그러나 우리는 실제 훈련을 먼저하고 싶어서 우리 논문에 대해 보여줄 것이 있습니다. 뒤늦은 지혜로는 이상적인 선택 이었지만 여전히 잘 진행되었지만 그렇지 않은 경우 최종 발표를 위해 제 시간에 프로젝트를 적절하게 시연하지 못했을 것입니다.
3.2.1 A Self-Adjusting Buffer
성능 문제를 해결하기까지 마침내 몇 달이 걸렸지 만, 중소 규모의 수백 가지 개선 사항을 모아 놓은 단일 수정본이 없었습니다. 주요 문제는 SigmaDiff 수학 프로세서가 연산을 처리하는 방식이었습니다. 모든 연산에 대해 결과 데이터에 대한 사본이 작성되었습니다. 그것은 더해졌습니다. 역 분화에는 모든 중간 값이 필요하기 때문에 복사가 필요했기 때문에 사물을 복사 할 수 없었습니다. 실행되는 연산을 가로 지르는 방법이 없었기 때문에 정적 인 방법으로 모든 필요한 버퍼를 생성 할 수 없었습니다. 계산 그래프는 매번 새로 작성되며 완전히 완료 할 수는 없습니다. 그들에게 의존하여 변하지 않게하십시오. 어쨌든 안정적인 버퍼링 방법을 도입하기 위해 세션 개념을 도입했습니다. 세션은 여러 번 반복되는 작업 집합을 의미합니다. 본질적으로 반복. 세션이 시작될 때 생성 된 모든 배열을 자체 저장소에 저장하기 시작합니다. 동일한 차원의 배열이 다음 세션에서 요청되었을 때 새로운 세션을 할당하지 않고 마지막 세션의 배열을 반환 할 수 있습니다. 지난 시간보다 더 많은 메모리가 필요하다면 여전히 메모리를 할당 할 수 있습니다. 사용량이 적 으면 다음 세션에서이를 버려서이를 깔끔하게 자체 조정할 수 있습니다. 세션 내에서 생성되었지만 다음 매개 변수 (예 : 매개 변수)에 필요한 데이터를 덮어 쓰지 않으려면 명시 적으로 "limbo"버퍼를 추가했습니다. 기본적으로이 버퍼는 런타임에 특정 배열에 대해 플래그로 설정 될 수있는 플래그였습니다. "재사용하지 마라".
3.2.2 SIMD and Avoiding Intermediate Allocation
다른 중요한 성능 향상은 SIMD 명령어 (CPU 바운드 산술 연산을 위해 동시에 8 개의 값을 동시에 처리 할 수있게 함)를 추가하는 것이 었습니다. 가능한 경우 중간 값이 엄격하게 필요하지 않은 경우에는 적절한 내부 연산을 추가하여 다른 메모리 할당을 최소화하십시오. 예를 들어 중간 값이 사용되지 않기 때문에 다중 피연산자가있는 노드에서 백 프로 시저 중 그라디언트를 누적 할 때 결과를 복사 할 필요가 없습니다. 프로파일 러를 분석하여 분석 한 결과, 결국 MNIST 샘플의 반복 시간이 18ms의 릴리스 구성으로 단축되었습니다 (약 17 배의 속도 향상). 덧붙여 말하면, 코어가 너무 빨라서 시각 자료가 때때로 들어오는 모든 데이터를 따라갈 수 없기 때문에 추락하기도합니다.
3.3 Monitoring with Sigma
3.3.1 The monitoring System
시그마를 개발할 때, 우리는 "수학적"백엔드에 중점을 두었을뿐만 아니라 모든 애플리케이션을 시그마 위에 구축 할 수있는 기능이 풍부한 모니터링 시스템을 구현했습니다 (또는 더 나은 시그마 코어). 모든 매개 변수를 관찰 할 수 있으며, 모든 변경 사항은 연결되며 모든 매개 변수는 관리됩니다. 이 모니터링 시스템을 사용하여 일반적으로 시그마 및 기계 학습을 학습하는 데 사용할 수있는 모니터 (즉, 애플리케이션)를 구축했습니다.
3.3.2 The WPF Monitor
사용자는 Sigma를 사용할 수있을뿐만 아니라 Sigma를 통해 배울 수 있어야합니다. 이 문제를 해결하기 위해 사용자가 Sigma와 상호 작용할 수있는 기능이 풍부한 응용 프로그램 (WPF 사용)을 구축했습니다. 그래프를 학습하고, 매개 변수를 관리하고, 음악 플레이어를 제어하는 것처럼 AI를 제어 할 수 있습니다. 이 모니터는 시그마의 다른 모든 구성 요소와 마찬가지로 완벽하게 사용자 정의 및 확장이 가능합니다. 모든 구성 요소는 재사용 가능성을 염두에두고 설계되었으므로 사용자는 기본 모니터 위에 복잡한 응용 프로그램을 직접 빌드 할 수 있습니다. 하지만 그래픽 사용자 인터페이스를 설명하는 이유는 무엇입니까? 직접보기, 여기 UI (그리고 시그마)가 실제로 작동합니다. (시그마의 예제 빌드는 GitHub에서 다운로드 할 수 있습니다).
3.4 CUDA Support and Finishing Touches
불과 2 개월 전에 우리는 CUDA 지원 추가, 많은 안정성 문제 해결 및 우리를 괴롭히는 거친 반점 제거를 시작하여 프레임 워크를 마무리하고 연마했습니다. 백엔드는 설계 상 개별 레이어를 이해하지 못하고 원시 계산 그래프 만 이해하기 때문에 CuDNL이 아닌 CuBLAS 만 사용할 수 있으므로 CUDA 지원 부분은 특히 까다 롭습니다. 앞에서 설명한 세션 논리의 문제가있는 부작용은 버퍼가 해제 될 때 보장되지 않았기 때문입니다. 이는 버퍼가 해제 될 때 비 결정적 GC의 작업이었습니다. CUDA 장치 메모리를 누설하지 않기 위해 장치 메모리 할당 자에 대한 자체 베어 본 참조 카운터를 추가했습니다. 장치 메모리 할당자는 버퍼 작성 / 완료시 업데이트되며 이는 놀랍게 잘 작동합니다. CuBLAS를 사용하여 커스터마이징 된 최적화 커널과 많은 밤에 우리는 단일 GTX 1080에서 동일한 샘플에 대해 약 5ms / 반복을 달성했으며, 이는 우리의 계획된 사용 사례에 대해 허용 가능하다고 판단했습니다.
4. Conclusion
약 3000 시간의 결합 된 시간, 수만 줄의 코드 및 많은 긴 밤 나중에 우리는 그것이 무엇인지 합리적으로 사용할 수 있다고 판단되는 것을 드디어 자랑스럽게 생각합니다 : 시그마 (Sigma)는 기계 학습에 대한 약간의 이해를 돕는 기계 학습 프레임 워크입니다. 현재 우리는 Sigma에 많은 새로운 기능을 추가하지 않을 것입니다. 주로 우리가 현재 사용 가능한 대부분의 시간을 차지하고있는 새로운 프로젝트에 참여하고 있기 때문입니다. 기본 기능이 많이 부족하더라도 (가장 중요한 것은 기본 프레임 유형의 호스트가 다른 프레임 워크에서 제공하는 기능) 우리는 프로젝트에 얼마나 멀리 도달했는지에 대해 매우 만족하며 2 년 전에 원래의 질문에 대한 적절한 업데이트가되기를 바랍니다. 여러분 중 일부가 그것을 확인하고 피드백을 줄 수 있다면 우리는 행복 할 것입니다.
4.1 The Cost of Creating a Machine Learning Framework
시간을 제외하고는 매우 쌉니다. 솔직히, 약간의 사전 프로그래밍 경험으로 (저레벨 프로그래밍 부분이 문제가되지 않도록), 모든 것이 굉장히 어렵지는 않으며, 충분한 시간이 주어진다면 대부분의 사람들이 할 수있는 일일 것입니다. 많은 시간. 전체적으로 우리는 대략 다음과 같이 우리를 데려갔습니다.
- Some 600 hours of research
- Some 2400 hours of development
- 2 tortured souls, preferably sold to the devil in exchange for less bugs
우리는 오랫동안 제대로 계산을 멈추었으므로이 숫자들을 소금 한알로 가져 가고, 하지만 그들은 적절한 야구장에 있어야합니다.
4.2 Final remarks
대체로이 같은 사업은 매우 시간 집약적입니다. 고교 졸업 논문은 매우 과잉이었습니다. 우리는 그것을 알았지만, 점점 더 정교 해지고 있습니다. 근본적으로 우리가 이용할 수있는 모든 시간을 채우고, 그 다음에는 몇 시간을 다 써 버렸습니다. 그것은 확실히 가치가 있었지만, 이제 우리는 일들이 어떻게 저수준에서 작동 하는지를 확실하게 이해하고 있으며, 가장 중요한 것은 우리가 기계 학습 프레임 워크를 실제로 작성했다고 말할 수 있습니다. 이것은 우리에게 추가적인 자랑거리를 부여합니다 :)