edu.snu.dolphin.dnn.util.NeuralNetworkUtils.java Source code

Java tutorial

Introduction

Here is the source code for edu.snu.dolphin.dnn.util.NeuralNetworkUtils.java

Source

/*
 * Copyright (C) 2015 Seoul National University
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package edu.snu.dolphin.dnn.util;

import edu.snu.dolphin.dnn.conf.LayerConfigurationParameters;
import edu.snu.dolphin.dnn.layerparam.initializer.LayerParameterInitializer;
import edu.snu.dolphin.dnn.layers.LayerBase;
import edu.snu.dolphin.dnn.layers.LayerParameter;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.reef.tang.Configuration;
import org.apache.reef.tang.Injector;
import org.apache.reef.tang.Tang;
import org.apache.reef.tang.exceptions.InjectionException;
import org.apache.reef.tang.formats.ConfigurationSerializer;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

/**
 * Utility class for neural network.
 */
public final class NeuralNetworkUtils {

    private NeuralNetworkUtils() {
    }

    /**
     * Delimiter that is used for distinguishing dimensions of shapes.
     */
    private static final String SHAPE_DELIMITER = ",";

    /**
     * Converts a list of integers for a shape to a string.
     * @param dimensionList a list of integers for a shape.
     * @return a string for a shape.
     */
    public static String shapeToString(final List<Integer> dimensionList) {
        return StringUtils.join(dimensionList, SHAPE_DELIMITER);
    }

    /**
     * Converts an array of {@code int}s for a shape to a string.
     * @param dimensions an array of {@code int}s for a shape.
     * @return a string for a shape.
     */
    public static String shapeToString(final int[] dimensions) {
        return shapeToString(Arrays.asList(ArrayUtils.toObject(dimensions)));
    }

    /**
     * Converts a string for a shape to an array of integers.
     * @param shapeString a string for a shape.
     * @return an array of integers for a shape.
     */
    public static int[] shapeFromString(final String shapeString) {
        final String[] inputShapeStrings = shapeString.split(SHAPE_DELIMITER);
        final int[] inputShape = new int[inputShapeStrings.length];
        for (int i = 0; i < inputShapeStrings.length; ++i) {
            inputShape[i] = Integer.parseInt(inputShapeStrings[i]);
        }
        return inputShape;
    }

    public static int getShapeLength(final int[] shape) {
        if (shape.length < 1) {
            throw new IllegalArgumentException("the shape must have one or more dimensions");
        }

        int length = shape[0];
        for (int i = 1; i < shape.length; ++i) {
            length *= shape[i];
        }

        if (length > 0) {
            return length;
        } else {
            throw new IllegalArgumentException("the length of the shape must be positive: " + length);
        }
    }

    /**
     * De-serializes a set of serialized layer configurations to an array of layer configurations.
     * @param configurationSerializer a configuration serializer to deserialize the specified configuration set.
     * @param serializedLayerConfSet a set of serialized layer configurations.
     * @return an array of layer configurations.
     */
    public static Configuration[] deserializeLayerConfSetToArray(
            final ConfigurationSerializer configurationSerializer, final Set<String> serializedLayerConfSet) {
        final Configuration[] layerConfigurations = new Configuration[serializedLayerConfSet.size()];
        for (final String serializedLayerConfiguration : serializedLayerConfSet) {
            try {
                final Configuration layerConfiguration = configurationSerializer
                        .fromString(serializedLayerConfiguration);
                final int index = Tang.Factory.getTang().newInjector(layerConfiguration)
                        .getNamedInstance(LayerConfigurationParameters.LayerIndex.class);
                layerConfigurations[index] = layerConfiguration;
            } catch (final IOException exception) {
                throw new RuntimeException("IOException while de-serializing layer configuration", exception);
            } catch (final InjectionException exception) {
                throw new RuntimeException("InjectionException", exception);
            }
        }
        return layerConfigurations;
    }

    /**
     * Returns initial layer parameters using the specified injector and the specified array of configurations.
     * This assumes that the specified injector has all parameters that are needed to inject layer parameter initializer
     * instances except the configuration for each layer.
     * @param injector an injector used for injecting layer parameter initializer instances
     * @param layerInitializerConfs an array of configurations for injecting layer parameter initializer instances
     * @param inputShape an input shape for the neural network.
     * @return an array of initial layer parameters
     */
    public static LayerParameter[] getInitialLayerParameters(final Injector injector,
            final Configuration[] layerInitializerConfs, final String inputShape) {
        final LayerParameter[] layerParameters = new LayerParameter[layerInitializerConfs.length];

        String currentInputShape = inputShape;
        for (final Configuration layerInitializerConf : layerInitializerConfs) {
            try {
                // bind an input shape for the layer.
                final Configuration finalInitializerConf = Tang.Factory.getTang()
                        .newConfigurationBuilder(layerInitializerConf)
                        .bindNamedParameter(LayerConfigurationParameters.LayerInputShape.class, currentInputShape)
                        .build();
                final LayerParameterInitializer layerParameterInitializer = injector
                        .forkInjector(finalInitializerConf).getInstance(LayerParameterInitializer.class);
                final int index = layerParameterInitializer.getIndex();

                layerParameters[index] = layerParameterInitializer.generateInitialParameter();
                currentInputShape = shapeToString(layerParameterInitializer.getOutputShape());

            } catch (final InjectionException exception) {
                throw new RuntimeException("InjectionException during injecting LayerParameterInitializer",
                        exception);
            }
        }
        return layerParameters;
    }

    /**
     * Returns layer instances using the specified injector and the specified array of configurations.
     * This assumes that the specified injector has all parameters that are needed to inject layer instances
     * except the configuration for each layer.
     * @param injector an injector used for injecting layer instances
     * @param layerConfs an array of configurations for injecting layer instances
     * @param inputShape an input shape for the neural network.
     * @return an array of layer instances.
     */
    public static LayerBase[] getLayerInstances(final Injector injector, final Configuration[] layerConfs,
            final String inputShape) {
        final LayerBase[] layers = new LayerBase[layerConfs.length];

        String currentInputShape = inputShape;
        for (final Configuration layerConf : layerConfs) {
            try {
                // bind an input shape for the layer.
                final Configuration finalLayerConf = Tang.Factory.getTang().newConfigurationBuilder(layerConf)
                        .bindNamedParameter(LayerConfigurationParameters.LayerInputShape.class, currentInputShape)
                        .build();
                final LayerBase layer = injector.forkInjector(finalLayerConf).getInstance(LayerBase.class);

                layers[layer.getIndex()] = layer;
                currentInputShape = shapeToString(layer.getOutputShape());

            } catch (final InjectionException exception) {
                throw new RuntimeException("InjectionException while injecting LayerBase", exception);
            }
        }
        return layers;
    }
}