[목차]
(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(); } }