[목차]
(0) 환경 설정 : DL4J 개발 환경 설정 및 예제 설명 (完)
(1) Data Iterator : 사용하고자 하는 데이터를 DL4J 에서 사용가능한 형태로 변환하는 작업 개발 필요
• Canova: The Rosetta Stone of Vectorization
• Spark
• Hadoop
• JDBC
•Text ,CSV (完)
• Image
• Sound
• Video
(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 : 분석 중간 발생하는 이벤트를 받아서 처리 및 결과에 대한 검증 및 비지니스 연동 등
(7) 모델 저장 및 로딩
• 매번 모든 데이터를 로딩하여 학습 시키는 것이 아니라, 모델 자체를 저장하고, 새로 발생하는 데이터만 학습 시킴으로써,
모델의 즉각적인 학습효과와 대량 데이터 처리에 따른 Performacne 문제를 해결 할수 있을 것으로 보임
http://deeplearning4j.org/modelpersistence
1. Save an Interoperable Vector of All Weights
– Neural Network 의 Cofiguration 값을 JSON 형태로 저장
– Neuron 의 모든 Weight 값과 Bias 값 등을 Binary 형태로 저장
– 아래는 모델을 저장하고 로딩하는 Sample 코드 이다, Code 상에는 File 로 되어 있지만,
Binary 형태로 변환하여 DB 에 Save & Load 를 하는 것도 가능할 것으로 보인다.
[Sample Code]
// 네트워크 파라메터 저장
try(DataOutputStream dos = new DataOutputStream(Files.newOutputStream(Paths.get("coefficients.bin")))){
Nd4j.write(net.params(),dos);
}
//네트워크 Configuration 저장
FileUtils.write(new File("conf.json"), net.getLayerWiseConfigurations().toJson());
//네트워크 Configuration 로딩
MultiLayerConfiguration confFromJson = MultiLayerConfiguration.fromJson(FileUtils.readFileToString(new File("conf.json")));
//네트워크 파라메터 로딩
INDArray newParams;
try(DataInputStream dis = new DataInputStream(new FileInputStream("coefficients.bin"))){
newParams = Nd4j.read(dis);
}
//저장된 정보로 네트워크 생성
MultiLayerNetwork savedNetwork = new MultiLayerNetwork(confFromJson);
savedNetwork.init();
savedNetwork.setParameters(newParams);
데이터를 로딩한 후에 계속해서 Training 을 진행하고 싶다면, 네트워크의 부분만 저장하는 방법을 사용한다.
더 이상 Training 이 필요 없는 경우 더 이상 Save & Load 를 할 필요가 없다.
데이터 트레이닝에 momentum, AdaGrad and RMSProp와 같은 기법을 사용하는데, 이러한 기법들은
Trainging 의 이력을 남긴다. 이러한 이력 값 없이 그냥 파라메터를 저장하고 로딩할 경우 이후에 발생하는
Training 에서 데이터가 외곡될 가능성이 크다. 이러한 것을 방지하기 위해서 Update 를 저장하는 방법은
아래와 같다.
[Code Sample]
// Update 를 저장
try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("updater.bin"))){
oos.writeObject(model.getUpdater());
}
//Update 를 로드
org.deeplearning4j.nn.api.Updater updater;
try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("updater.bin"))){
updater = (org.deeplearning4j.nn.api.Updater) ois.readObject();
}
//Update 값을 모델에 사용
model.setUpdater(updater);
– Model Util을 사용해서 모델을 업데이트하고 로드하는 예제
– 모델의 Save & Load 를 사용하여 한번에 대량의 데이터를 로딩하지 않음으로써,
서버의 부하를 줄이고, 지속적으로 발생하는 데이터를 학습시켜 모델의 정합성을
올리는 방식으로 사용할 수 있지 않을까 기대 함
/**
* Project utility class to save and load models and parameters.
*/
@Deprecated
public class ModelUtils {
private static final Logger log = LoggerFactory.getLogger(ModelUtils.class);
private ModelUtils(){}
public static void saveModelAndParameters(MultiLayerNetwork net, String basePath) {
String confPath = FilenameUtils.concat(basePath, net.toString()+"-conf.json");
String paramPath = FilenameUtils.concat(basePath, net.toString() + ".bin");
log.info("Saving model and parameters to {} and {} ...", confPath, paramPath);
// save parameters
try {
DataOutputStream dos = new DataOutputStream(new FileOutputStream(paramPath));
Nd4j.write(net.params(), dos);
dos.flush();
dos.close();
// save model configuration
FileUtils.write(new File(confPath), net.conf().toJson());
} catch (IOException e) {
e.printStackTrace();
}
}
public static MultiLayerNetwork loadModelAndParameters(File confPath, String paramPath) {
log.info("Loading saved model and parameters...");
MultiLayerNetwork savedNetwork = null;
// load parameters
try {
MultiLayerConfiguration confFromJson = MultiLayerConfiguration.fromJson(FileUtils.readFileToString(confPath));
DataInputStream dis = new DataInputStream(new FileInputStream(paramPath));
INDArray newParams = Nd4j.read(dis);
dis.close();
// load model configuration
savedNetwork = new MultiLayerNetwork(confFromJson);
savedNetwork.init();
savedNetwork.setParams(newParams);
} catch (IOException e) {
e.printStackTrace();
}
return savedNetwork;
}
public static void saveLayerParameters(INDArray param, String paramPath) {
// save parameters for each layer
log.info("Saving parameters to {} ...", paramPath);
try {
DataOutputStream dos = new DataOutputStream(new FileOutputStream(paramPath));
Nd4j.write(param, dos);
dos.flush();
dos.close();
} catch(IOException e) {
e.printStackTrace();
}
}
public static Layer loadLayerParameters(Layer layer, String paramPath) {
// load parameters for each layer
String name = layer.conf().getLayer().getLayerName();
log.info("Loading saved parameters for layer {} ...", name);
try{
DataInputStream dis = new DataInputStream(new FileInputStream(paramPath));
INDArray param = Nd4j.read(dis);
dis.close();
layer.setParams(param);
} catch(IOException e) {
e.printStackTrace();
}
return layer;
}
public static void saveParameters(MultiLayerNetwork model, int[] layerIds, Map<Integer, String> paramPaths) {
Layer layer;
for(int layerId: layerIds) {
layer = model.getLayer(layerId);
if (!layer.paramTable().isEmpty()) {
ModelUtils.saveLayerParameters(layer.params(), paramPaths.get(layerId));
}
}
}
public static void saveParameters(MultiLayerNetwork model, String[] layerIds, Map<String, String> paramPaths) {
Layer layer;
for(String layerId: layerIds) {
layer = model.getLayer(layerId);
if (!layer.paramTable().isEmpty()) {
ModelUtils.saveLayerParameters(layer.params(), paramPaths.get(layerId));
}
}
}
public static MultiLayerNetwork loadParameters(MultiLayerNetwork model, int[] layerIds, Map<Integer, String> paramPaths) {
Layer layer;
for(int layerId: layerIds) {
layer = model.getLayer(layerId);
loadLayerParameters(layer, paramPaths.get(layerId));
}
return model;
}
public static MultiLayerNetwork loadParameters(MultiLayerNetwork model, String[] layerIds, Map<String, String> paramPaths) {
Layer layer;
for(String layerId: layerIds) {
layer = model.getLayer(layerId);
loadLayerParameters(layer, paramPaths.get(layerId));
}
return model;
}
public static Map<Integer, String> getIdParamPaths(MultiLayerNetwork model, String basePath, int[] layerIds){
Map<Integer, String> paramPaths = new HashMap<>();
for (int id : layerIds) {
paramPaths.put(id, FilenameUtils.concat(basePath, id + ".bin"));
}
return paramPaths;
}
public static Map<String, String> getStringParamPaths(MultiLayerNetwork model, String basePath, String[] layerIds){
Map<String, String> paramPaths = new HashMap<>();
for (String name : layerIds) {
paramPaths.put(name, FilenameUtils.concat(basePath, name + ".bin"));
}
return paramPaths;
}
public static String defineOutputDir(String modelType){
String tmpDir = System.getProperty("java.io.tmpdir");
String outputPath = File.separator + modelType + File.separator + "output";
File dataDir = new File(tmpDir,outputPath);
if (!dataDir.getParentFile().exists())
dataDir.mkdirs();
return dataDir.toString();
}
}