[DL4J] DL4J-Quick Start

[목차]

(0) 환경 설정 : DL4J 개발 환경 설정 및 예제 설명

(1) Data Iterator : 사용하고자 하는 데이터를 DL4J 에서 사용가능한 형태로 변환하는 작업 개발 필요

• Canova: The Rosetta Stone of Vectorization

(2) Net : 사용할 신경망의 형태가 어떤 것이 있는지 이해하고 선택, 활용 할 수 있어야 함
• Restricted Boltzmann machines
• Convolutional nets
• Recursive autoencoders
• Recurrent nets: Long Short-Term Memory (LSTM) (including bi-directional LSTMs)
• Deep-belief networks
• Denoising and Stacked Denoising autoencoders
• Deep autoencoders

(3) Activation : Weight + Bias 결과 다음 적용할 함수 결정 (예 : SigMoid : Chap1 에서 설명한 것)

• ReLU
• Leaky ReLU
• Tanh
• Sigmoid
• Hard Tanh
• Softmax
• Identity
• ELU: Exponential Linear Units
• Softsign
• Softplus

(4) Loss&Objective Functions : 일부 데이터를 누락함으로써 더 Robust 한 모델을 만들 수 있다.
• Reconstruction entropy
• Squared loss
• Mean squared error
• Multi-class cross entropy for classification
• Negative log likelihood
• RMSE_XENT

(5) Hyperparameters : 모든 Layer 에 공통적으로 적용되는 파라메터로 숙지 필요

• Dropout (random ommission of feature detectors to prevent overfitting)
• Sparsity (force activations of sparse/rare inputs)
• Adagrad (feature-specific learning-rate optimization)
• L1 and L2 regularization (weight decay)
• Weight transforms (useful for deep autoencoders)
• Probability distribution manipulation for initial weight generation
• Gradient normalization and clipping

(6) Event Listener & Result Anal : 분석 중간 발생하는 이벤트를 받아서 처리 및 결과에 대한 검증 및 비지니스 연동 등

DL4J 는 InteliJ 기반으로 개발됩니다. 홈페이지에 친절하게 환경 구성 과정이 설명되어 있습니다. (http://deeplearning4j.org/quickstart)

그럼에도 불구하고 간단하게 내용을 정리해 보도록 하겠습니다.

1. 환경 구성 사전 필수 조건

– Java 7 or later

– IntelliJ (Eclipse 도 가능은 하지만 InteliJ 추천)

Maven (연관된 라이브러리 자동화 관리)

– Git (프로젝트 공유 관리)

위 내용은 DL4J 가 내부적으로 사용하는 과학적 데이터 처리 ND4J 홈페이지 설치 가이드 참조라고 되어 있음

※ Check 사항

. Java JDK 만 있으면 됩니다. JRE는 건들지 마세요. InteliJ 에서 SDK Setting 에 들어가서 경로만 걸어 주세요

. Maven 압축말 풀어서 Path 만 잡아주면 됩니다. MAVEN_HOME 설정해 주시면 InteliJ 는 자동으로 연동됩니다.

회사에서 개발시 Proxy 문제 발생 할 수 있습니다. InteliJ 에서 Proxy 만 잡아주세요

. Git : 윈도우 버전 설치시 계속만 열시히 눌러주면 됩니다.

2. Sample 실행해 보기

– git 사용 Sample 프로젝트 다운로드

. git 콘솔 실행

. 명령어 입력 : git clone https://github.com/deeplearning4j/dl4j-0.4-examples.git

. git 하위 폴더에 프로젝트 다운로드

. InteliJ 에서 기존소스 열기로 해당 프로젝트 오픈

– Maven 사용 필요 라이브러리 다운로드

. InteliJ 에서 프로젝트 import 시 라이브러리 없음으로 애러 발생

. Maven Reimport 수행

– 각 Sample 프로젝트 실행

. 다수의 Sample 을 포함하고 있는 프로젝트로 개별적으로 RUN 하여 테스트

※ Image 를 서버에서 다운받아 사용하는 예제의 경우 Proxy 문제로 소스 코드 수정 필요

3. 예제 소스 보기

– NeuralNetConfiguration 에 신경망 설계 내용이 들어간다.

(1) 데이터 Set

분석에서는 엄청 유명한 데이터 셋 Iris

EX) 5.1,3.5,1.4,0.2,i.setosa

1. sepal length in cm
2. sepal width in cm
3. petal length in cm
4. petal width in cm
5. class (Iris Setosa) , (Iris Versicolour) , (Iris Virginica)

(2) 데이터 로딩

신경망 분석이 가능한 형태로 데이터를 변환하는 과정

IrisDataSetIterator 는 CSV 파일을 신경망 분석이 가능한 데이터로 변환하는 클래스로

Canova(http://deeplearning4j.org/canova.html) 를 사용해서 만든 예제 클래스 중에 하나임

※ Canova 는 Text, CSV, Image, Audio 등 대표적인 데이터 타입을 신경망 분석 가능한 형태로

변환하는 라이브러리임( 해당 라이브러리 사용법에 대해서는 추후에 다루는 것으로)

– IrisDataSetIterator(batchSize, numSamples)

. batchSize : 한번에 읽는 데이터의 양

. numSamples : 전체 로딩하고자 하는 데이터의 양

– next.normalizeZeroMeanZeroUnitVariance()

. Nomalization 스케일링 작업 (너무 크거나 작은 값은 결과에 외곡을 줄수 있음)

[코드]

log.info("Load data....");

DataSetIterator iter = new IrisDataSetIterator(batchSize, numSamples);

DataSet next = iter.next();

next.normalizeZeroMeanZeroUnitVariance();

 

(3) 학습 데이터 분리

R 분석에서도 항상 하는 것 처럼 데이터를 학습할 데이터와 검증할 데이터로 나누는 작업이다.

[코드]

log.info("Split data....");

SplitTestAndTrain testAndTrain = next.splitTestAndTrain(splitTrainNum, new Random(seed));

DataSet train = testAndTrain.getTrain();

DataSet test = testAndTrain.getTest();

 

(4) 신경망 구성 작업

가) HyperParameters

신경망에서는 각 Neuron 의 Weight 와 Bias 값 등을 Parameter 라고 부르며 아래와 같이 전체적인

망 구성의 옵션으로 적용되는 것들은 HyperParmeter 라고 부른다고 한다..

conf 값은 orvering 을 통해 각 Layer 별로 지정해 주지 않는한 모든 Layer 에 공통적으로 적용된다.

파라메터는 Builder() 뒤 쪽으로 연결해서 정의된다.

[코드]

MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()

 

나) Seed 값 지정

시드 값은 통상적인 프로그램에서와 마찬가지로 Random 값 생성시 사용하는 값으로

일정한 결과를 유지하기 위하여 지정한다.

[코드]

.seed(seed)

 

다) 학습 반복 횟수 지정

분류 및 저장을 반복할 횟수를 지정하는 것

(Epoch 와 Iteration 은 다른것이라고 하는데 확실히 이해는 안됨..??)

[코드]

.iterations(iterations)

 

라) 학습 반영도

학습이라 함은 간단하게 생각하면 Weight 값과 Bias 값의 조정이라고 보고 한번의

Iteration 으로 Weight 에 얼마나 변화를 줄 것 인지를 지정하는 것

[코드]

.learningRate(1e-6f)

 

마) 최적화 알고리즘 지정

신경막을 역방향으로 분석할 때 사용할 알고리즘을 지정하는 것

. LBFGS : Limited-memory BFGS

 

[코드]

.optimizationAlgo(OptimizationAlgorithm.LBFGS)

 

바) 기타 파라메터

[코드]

.regularization(true).momentum(0.9).constrainGradientToUnitNorm(true)

 

사) 데이터 누락

의도적으로 랜덤하게 데이터를 누락하는 것은 모델을 더 견고하게 만드는데 도움이 됨

[코드]

.useDropConnect(true)

 

아) Layer Depth

Layer 의 수를 지정한다. 2라고 함은 각 하나의 Input , Hidden, Output Layer 를 만들라는 말이다.

[코드]

.list(2)

 

사) 레이어 종류 지정

RBM 은 restricted Boltzmann machine 으로 같은 Level 끼리는 연결 관계를 갖지 않는 형태의

신경망을 이야기하며, 더 자세한 설명은 따로 정리하도록 하겠다.

파라메터를 보면 Hidden Layer 를 만드는데는 ReLU (Rectified linear units) 을 사용하여 더

견고하고 F1 점수가 높은(학습데이터와 테스트 데이터가 더 일치하는) Activation (Weight 와 Bias 로

구성된 Function) 을 만드는데 사용하고, Data Input 을 위한 Visible Layer 에는 가우시안 화이트 노이즈

(정규 분포를 어떻게 사용하는듯..??) 사용한다.

[코드]

.layer(0, new RBM.Builder(RBM.HiddenUnit.RECTIFIED, RBM.VisibleUnit.GAUSSIAN)

 

마) 인풋 데이터

인풋 노드의 수를 정의한다. (10 by 10 이미지를 Pixel 단위로 Input 데이터로 정의하면 100개)

본 예 에서는 아래와 같은 4가지의 인풋을 갖기 때문에 4이다.

원문서에서 Row 4 X Col 1 = 4라고 하는것은 Matrix 개념으로 설명했다고 보면 된다.

1. sepal length in cm
2. sepal width in cm
3. petal length in cm
4. petal width in cm

[코드]

.nIn(numRows * numColumns)

 

바) 아웃풋 데이터

아웃풋 노드의 수를 지정한다. 본 예에서는 아래와 같이 3가지로 outputNum 는 3이다,

class (Iris Setosa) , (Iris Versicolour) , (Iris Virginica)

[코드]

.nOut(outputNum)'

 

아) 초기 Weight 설정

초기 Weight 값 설정에 사용할 알고리즘을 정의한다. Xavier initialization 는 많은 Layer 를

거쳐 특정 값이 너무 커지거나 너무 작아지지 않도록 도와준다

[코드]

.weightInit(WeightInit.XAVIER)

 

차) Activation Function 지정

Rectified linear units 가 두번 정의되는데 인풋에서 한번 아웃풋에서 한번 정의되어

변화없이 값을 전달 할 수 있도록 한다.

[코드]

.activation("relu")

 

카) 오류치 계산 알고리즘

학습알고리즘은 Error 치가 적은 방향으로 점진적으로 조정해 가는데 이때 오류치를 구하는

방법을 지정한다. root-means-squared-error-cross entropy는 큰 오류치를 찾는데 효과적이라고 한다..

[코드]

.lossFunction(LossFunctions.LossFunction.RMSE_XENT)

(5) Net Build

Line1 : (4) configuration 값을 세팅

Line2 : Configuration 값으로 MultiLayerNetwork 을 생성

Line3 : 모델 초기화

Line4 : interation 에서 발생하는 Event Call Back

[코드]

.build();

MultiLayerNetwork model = new MultiLayerNetwork(conf);

model.init();

model.setListeners(Collections.singletonList((IterationListener) new ScoreIterationListener(listenerFreq)));

 

(6) 모델 학습

위에서 생서한 Train Data Set 으로 모델을 훈련한다.

[코드]

log.info("Train model....");

model.fit(train);

 

(7) 모델 실행 평가

(6)의 테스트 데이터로 만든 모델에 Test Data 로 시뮬레이션을 실행하고

원래 원본에서 알고 있는 값과 비교를 통해 정확도를 평가한다.

가장 가단한 예제 하나를 실행하여 본 것이지만 R 에서 제공하는 RANN 과

차이와 장단점 비교를 하지 않을 수 없을 것 같다는 생각이 든다..

[코드]

log.info("Evaluate model....");

Evaluation eval = new Evaluation();

INDArray output = model.output(test.getFeatureMatrix());

for (int i = 0; i < output.rows(); i++) {

String actual = train.getLabels().getRow(i).toString().trim();

String predicted = output.getRow(i).toString().trim();

log.info("actual " + actual + " vs predicted " + predicted);

}

 

[결과 값]

Actual Class 0 was Predicted 0 with count 13 times
Actual Class 1 was Predicted 0 with count 2 times
Actual Class 1 was Predicted 2 with count 8 times
Actual Class 2 was Predicted 2 with count 7 times
=================Scores=========================
Accuracy: 0.6667
Precision: 0.6667
Recall: 1
F1 Score: 0.8
================================================

 

[전체 코드]

public class DBNIrisExample {

private static Logger log = LoggerFactory.getLogger(DBNIrisExample.class);

public static void main(String[] args) throws Exception {
// Customizing params
Nd4j.MAX_SLICES_TO_PRINT = -1;
Nd4j.MAX_ELEMENTS_PER_SLICE = -1;

final int numRows = 4;
final int numColumns = 1;
int outputNum = 3;
int numSamples = 150;
int batchSize = 150;
int iterations = 5;
int splitTrainNum = (int) (batchSize * .8);
int seed = 123;
int listenerFreq = 1;

log.info("Load data....");
DataSetIterator iter = new IrisDataSetIterator(batchSize, numSamples);
DataSet next = iter.next();
next.shuffle();
next.normalizeZeroMeanZeroUnitVariance();

log.info("Split data....");
SplitTestAndTrain testAndTrain = next.splitTestAndTrain(splitTrainNum, new Random(seed));
DataSet train = testAndTrain.getTrain();
DataSet test = testAndTrain.getTest();
Nd4j.ENFORCE_NUMERICAL_STABILITY = true;

log.info("Build model....");
MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()
.seed(seed) // Locks in weight initialization for tuning
.iterations(iterations) // # training iterations predict/classify & backprop
.learningRate(1e-6f) // Optimization step size
.optimizationAlgo(OptimizationAlgorithm.CONJUGATE_GRADIENT) // Backprop to calculate gradients
.l1(1e-1).regularization(true).l2(2e-4)
.useDropConnect(true)
.list(2) // # NN layers (doesn't count input layer)
.layer(0, new RBM.Builder(RBM.HiddenUnit.RECTIFIED, RBM.VisibleUnit.GAUSSIAN)
.nIn(numRows * numColumns) // # input nodes
.nOut(3) // # fully connected hidden layer nodes. Add list if multiple layers.
.weightInit(WeightInit.XAVIER) // Weight initialization
.k(1) // # contrastive divergence iterations
.activation("relu") // Activation function type
.lossFunction(LossFunctions.LossFunction.RMSE_XENT) // Loss function type
.updater(Updater.ADAGRAD)
.dropOut(0.5)
.build()
) // NN layer type
.layer(1, new OutputLayer.Builder(LossFunctions.LossFunction.MCXENT)
.nIn(3) // # input nodes
.nOut(outputNum) // # output nodes
.activation("softmax")
.build()
) // NN layer type
.build();
MultiLayerNetwork model = new MultiLayerNetwork(conf);
model.init();

model.setListeners(new ScoreIterationListener(listenerFreq));
log.info("Train model....");
model.fit(train);

log.info("Evaluate weights....");
for(org.deeplearning4j.nn.api.Layer layer : model.getLayers()) {
INDArray w = layer.getParam(DefaultParamInitializer.WEIGHT_KEY);
log.info("Weights: " + w);
}

log.info("Evaluate model....");
Evaluation eval = new Evaluation(outputNum);
eval.eval(test.getLabels(), model.output(test.getFeatureMatrix(), Layer.TrainingMode.TEST));
log.info(eval.stats());

log.info("****************Example finished********************");

OutputStream fos = Files.newOutputStream(Paths.get("coefficients.bin"));
DataOutputStream dos = new DataOutputStream(fos);
Nd4j.write(model.params(), dos);
dos.flush();
dos.close();
FileUtils.writeStringToFile(new File("conf.json"), model.getLayerWiseConfigurations().toJson());

MultiLayerConfiguration confFromJson = MultiLayerConfiguration.fromJson(FileUtils.readFileToString(new File("conf.json"))); DataInputStream dis = new DataInputStream(new FileInputStream("coefficients.bin"));
INDArray newParams = Nd4j.read(dis);
dis.close();
MultiLayerNetwork savedNetwork = new MultiLayerNetwork(confFromJson);
savedNetwork.init();
savedNetwork.setParams(newParams);
System.out.println("Original network params " + model.params());
System.out.println(savedNetwork.params());
}
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *