Commit db235679 authored by Evgeny Kusmenko's avatar Evgeny Kusmenko

Merge branch 'master' into 'word_embedding'

# Conflicts:
#   src/main/java/de/monticore/lang/monticar/cnnarch/predefined/AllPredefinedLayers.java
parents 20734cd3 d4c18ae4
Pipeline #201588 failed with stages
in 2 minutes and 58 seconds
......@@ -36,7 +36,7 @@ masterJobWindows:
script:
- mvn -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -B clean install --settings settings.xml
tags:
- Windows10
- Windows10_OS
BranchJobLinux:
stage: linux
......
......@@ -3,6 +3,13 @@
![coverage](https://git.rwth-aachen.de/monticore/EmbeddedMontiArc/languages/CNNArchLang/badges/master/coverage.svg)
# CNNArch
**!!Attention:
For all layers with padding: For the gluon backend currently only the default value is working ("same"). As there is and was the same
custom calculations done there is no behaviorial change to previous versions. See the following issue:
https://git.rwth-aachen.de/monticore/EmbeddedMontiArc/generators/cnnarch2x/issues/2
!!**
## Introduction
CNNArch is a descriptive language to model architectures of feedforward neural networks with a special focus on convolutional neural networks.
It is being developed for use in the MontiCar language family, along with CNNTrain, which configures the training of the network, and EmbeddedMontiArcDL, which integrates CNNArch into EmbeddedMontiArc.
......@@ -403,4 +410,13 @@ All predefined methods start with a capital letter and all constructed methods h
* **size** (integer > 0, optional): The OneHot-vector's size. Can be omitted to automatically use the output size of the architecture.
* **UpConvolution(kernel, channels, stride=(1,1), no_bias=false, padding="same")**
Creates a up convolutional layer (also known as transposed convolution ). Is currently only supported in the tesnsorflow backend.
* **kernel** (integer tuple > 0, required): convolution kernel size: (height, width).
* **channels** (integer > 0, required): number of up convolution filters and number of output channels.
* **stride** (integer tuple > 0, optional, default=(1,1)): up convolution stride: (height, width).
* **padding** ({"valid", "same", "no_loss"}, optional, default="same"): One of "valid", "same" or "no_loss". "valid" means no padding. "same" results in padding the input such that the output has the same length as the original input divided by the stride (rounded up). "no_loss" results in minimal padding such that each input is used by at least one filter (identical to "valid" if *stride* equals 1).
* **no_bias** (boolean, optional, default=false): Whether to disable the bias parameter.
......@@ -177,6 +177,32 @@ abstract public class PredefinedLayerDeclaration extends LayerDeclarationSymbol
}
}
//output type function for upconvolution
protected static List<ArchTypeSymbol> computeUpConvOutputShape(ArchTypeSymbol inputType, LayerSymbol method, int channels) {
String borderModeSetting = method.getStringValue(AllPredefinedLayers.PADDING_NAME).get();
if (borderModeSetting.equals(AllPredefinedLayers.PADDING_SAME)){
return computeOutputUpConvShapeWithSamePadding(inputType, method, channels);
}
else if (borderModeSetting.equals(AllPredefinedLayers.PADDING_VALID)){
return computeOutputUpConvShapeWithValidPadding(inputType, method, channels);
}
else if (borderModeSetting.equals(AllPredefinedLayers.PADDING_NO_LOSS)){
return computeOutputUpConvShapeWithNoLossPadding(inputType, method, channels);
}
else{
throw new IllegalStateException("border_mode is " + borderModeSetting + ". This should never happen.");
}
}
protected static void computeOneHotOutputSize(LayerSymbol layer){
int outputChannels = 0;
if (layer.getOutputElement().get() instanceof VariableSymbol && layer.getOutputElement().get().isOutput()) {
outputChannels = ((VariableSymbol) layer.getOutputElement().get()).getIoDeclaration().getType().getChannels();
}
layer.setIntValue(AllPredefinedLayers.SIZE_NAME, outputChannels);
}
//padding with border_mode=valid, no padding
private static List<ArchTypeSymbol> computeOutputShapeWithValidPadding(ArchTypeSymbol inputType, LayerSymbol method, int channels){
int strideHeight = method.getIntTupleValue(AllPredefinedLayers.STRIDE_NAME).get().get(0);
......@@ -242,7 +268,66 @@ abstract public class PredefinedLayerDeclaration extends LayerDeclarationSymbol
.elementType("-oo", "oo")
.build());
}
private static List<ArchTypeSymbol> computeOutputUpConvShapeWithValidPadding(ArchTypeSymbol inputType, LayerSymbol method, int channels){
int strideHeight = method.getIntTupleValue(AllPredefinedLayers.STRIDE_NAME).get().get(0);
int strideWidth = method.getIntTupleValue(AllPredefinedLayers.STRIDE_NAME).get().get(1);
int kernelHeight = method.getIntTupleValue(AllPredefinedLayers.KERNEL_NAME).get().get(0);
int kernelWidth = method.getIntTupleValue(AllPredefinedLayers.KERNEL_NAME).get().get(1);
int inputHeight = inputType.getHeight();
int inputWidth = inputType.getWidth();
int outputWidth;
int outputHeight;
outputWidth = (inputWidth - 1) * strideWidth + kernelWidth;
outputHeight = (inputHeight - 1) * strideHeight + kernelHeight;
return Collections.singletonList(new ArchTypeSymbol.Builder()
.height(outputHeight)
.width(outputWidth)
.channels(channels)
.elementType("-oo", "oo")
.build());
}
private static List<ArchTypeSymbol> computeOutputUpConvShapeWithNoLossPadding(ArchTypeSymbol inputType, LayerSymbol method, int channels){
int strideHeight = method.getIntTupleValue(AllPredefinedLayers.STRIDE_NAME).get().get(0);
int strideWidth = method.getIntTupleValue(AllPredefinedLayers.STRIDE_NAME).get().get(1);
int kernelHeight = method.getIntTupleValue(AllPredefinedLayers.KERNEL_NAME).get().get(0);
int kernelWidth = method.getIntTupleValue(AllPredefinedLayers.KERNEL_NAME).get().get(1);
int inputHeight = inputType.getHeight();
int inputWidth = inputType.getWidth();
int outputWidth = Math.max(0, ((inputWidth - 1) * strideWidth - strideWidth + kernelWidth + 1) );
int outputHeight = Math.max(0, ((inputHeight - 1) * strideHeight - strideHeight + kernelHeight + 1));
return Collections.singletonList(new ArchTypeSymbol.Builder()
.height(outputHeight)
.width(outputWidth)
.channels(channels)
.elementType("-oo", "oo")
.build());
}
private static List<ArchTypeSymbol> computeOutputUpConvShapeWithSamePadding(ArchTypeSymbol inputType, LayerSymbol method, int channels){
int strideHeight = method.getIntTupleValue(AllPredefinedLayers.STRIDE_NAME).get().get(0);
int strideWidth = method.getIntTupleValue(AllPredefinedLayers.STRIDE_NAME).get().get(1);
int inputHeight = inputType.getHeight();
int inputWidth = inputType.getWidth();
//no -strideWidth+1 at end as sugested by rearanging the corresponding formula for convolution. Tensorflow calculates it like this.
int outputWidth = inputWidth * strideWidth;
int outputHeight = inputHeight * strideHeight;
return Collections.singletonList(new ArchTypeSymbol.Builder()
.height(outputHeight)
.width(outputWidth)
.channels(channels)
.elementType("-oo", "oo")
.build());
}
protected List<String> computeStartAndEndValue(List<ArchTypeSymbol> inputTypes, BinaryOperator<Rational> startValAccumulator, BinaryOperator<Rational> endValAccumulator){
Stream.Builder<Rational> startValues = Stream.builder();
Stream.Builder<Rational> endValues = Stream.builder();
......
......@@ -18,6 +18,7 @@ public class AllPredefinedLayers {
//predefined layer names
public static final String FULLY_CONNECTED_NAME = "FullyConnected";
public static final String CONVOLUTION_NAME = "Convolution";
public static final String UP_CONVOLUTION_NAME = "UpConvolution";
public static final String SOFTMAX_NAME = "Softmax";
public static final String SIGMOID_NAME = "Sigmoid";
public static final String TANH_NAME = "Tanh";
......@@ -79,6 +80,7 @@ public class AllPredefinedLayers {
return Arrays.asList(
FullyConnected.create(),
Convolution.create(),
UpConvolution.create(),
Softmax.create(),
Sigmoid.create(),
Tanh.create(),
......@@ -98,7 +100,7 @@ public class AllPredefinedLayers {
LSTM.create(),
GRU.create(),
Embedding.create(),
Reshape.create());
Reshape.create()),
RNN.create());
}
}
/**
*
* (c) https://github.com/MontiCore/monticore
*
* The license generally applicable for this project
* can be found under https://github.com/MontiCore/monticore.
*/
package de.monticore.lang.monticar.cnnarch.predefined;
import de.monticore.lang.monticar.cnnarch._symboltable.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class UpConvolution extends PredefinedLayerDeclaration {
private UpConvolution() {
super(AllPredefinedLayers.UP_CONVOLUTION_NAME);
}
@Override
public List<ArchTypeSymbol> computeOutputTypes(List<ArchTypeSymbol> inputTypes, LayerSymbol layer, VariableSymbol.Member member) {
return computeUpConvOutputShape(inputTypes.get(0),
layer,
layer.getIntValue(AllPredefinedLayers.CHANNELS_NAME).get());
}
@Override
public void checkInput(List<ArchTypeSymbol> inputTypes, LayerSymbol layer, VariableSymbol.Member member) {
errorIfInputSizeIsNotOne(inputTypes, layer);
}
public static UpConvolution create(){
UpConvolution declaration = new UpConvolution();
List<ParameterSymbol> parameters = new ArrayList<>(Arrays.asList(
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.KERNEL_NAME)
.constraints(Constraints.INTEGER_TUPLE, Constraints.POSITIVE)
.build(),
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.CHANNELS_NAME)
.constraints(Constraints.INTEGER, Constraints.POSITIVE)
.build(),
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.STRIDE_NAME)
.constraints(Constraints.INTEGER_TUPLE, Constraints.POSITIVE)
.defaultValue(Arrays.asList(1, 1))
.build(),
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.NOBIAS_NAME)
.constraints(Constraints.BOOLEAN)
.defaultValue(false)
.build(),
new ParameterSymbol.Builder()
.name(AllPredefinedLayers.PADDING_NAME)
.constraints(Constraints.PADDING_TYPE)
.defaultValue(AllPredefinedLayers.PADDING_SAME)
.build()));
declaration.setParameters(parameters);
return declaration;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment