Commit c561d307 authored by Evgeny Kusmenko's avatar Evgeny Kusmenko

Merge branch 'develop' into 'master'

Shared code, updated for CNNArchLang

See merge request !27
parents e1dbf61a 8061de3a
Pipeline #158839 passed with stages
in 4 minutes and 29 seconds
......@@ -15,8 +15,9 @@
<properties>
<!-- .. SE-Libraries .................................................. -->
<CNNArch.version>0.3.0-SNAPSHOT</CNNArch.version>
<CNNArch.version>0.3.1-SNAPSHOT</CNNArch.version>
<CNNTrain.version>0.3.4-SNAPSHOT</CNNTrain.version>
<CNNArch2X.version>0.0.2-SNAPSHOT</CNNArch2X.version>
<embedded-montiarc-math-opt-generator>0.1.4</embedded-montiarc-math-opt-generator>
<!-- .. Libraries .................................................. -->
......@@ -87,6 +88,12 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.monticore.lang.monticar</groupId>
<artifactId>cnnarch-generator</artifactId>
<version>${CNNArch2X.version}</version>
</dependency>
<dependency>
<groupId>de.monticore.lang.monticar</groupId>
<artifactId>embedded-montiarc-math-opt-generator</artifactId>
......@@ -102,6 +109,12 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
......
/**
*
* ******************************************************************************
* MontiCAR Modeling Family, www.se-rwth.de
* Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
* All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package de.monticore.lang.monticar.cnnarch.mxnetgenerator;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchTypeSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchitectureElementSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.LayerSymbol;
import de.monticore.lang.monticar.cnnarch.predefined.AllPredefinedLayers;
import de.se_rwth.commons.logging.Log;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.List;
public class ArchitectureElementData {
private String name;
private ArchitectureElementSymbol element;
private CNNArchTemplateController templateController;
public ArchitectureElementData(String name, ArchitectureElementSymbol element, CNNArchTemplateController templateController) {
this.name = name;
this.element = element;
this.templateController = templateController;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArchitectureElementSymbol getElement() {
return element;
}
public void setElement(ArchitectureElementSymbol element) {
this.element = element;
}
public CNNArchTemplateController getTemplateController() {
return templateController;
}
public void setTemplateController(CNNArchTemplateController templateController) {
this.templateController = templateController;
}
public List<String> getInputs(){
return getTemplateController().getLayerInputs(getElement());
}
public List<Integer> getKernel(){
return ((LayerSymbol) getElement())
.getIntTupleValue(AllPredefinedLayers.KERNEL_NAME).get();
}
public int getChannels(){
return ((LayerSymbol) getElement())
.getIntValue(AllPredefinedLayers.CHANNELS_NAME).get();
}
public List<Integer> getStride(){
return ((LayerSymbol) getElement())
.getIntTupleValue(AllPredefinedLayers.STRIDE_NAME).get();
}
public int getUnits(){
return ((LayerSymbol) getElement())
.getIntValue(AllPredefinedLayers.UNITS_NAME).get();
}
public boolean getNoBias(){
return ((LayerSymbol) getElement())
.getBooleanValue(AllPredefinedLayers.NOBIAS_NAME).get();
}
public double getP(){
return ((LayerSymbol) getElement())
.getDoubleValue(AllPredefinedLayers.P_NAME).get();
}
public int getIndex(){
return ((LayerSymbol) getElement())
.getIntValue(AllPredefinedLayers.INDEX_NAME).get();
}
public int getNumOutputs(){
return ((LayerSymbol) getElement())
.getIntValue(AllPredefinedLayers.NUM_SPLITS_NAME).get();
}
public boolean getFixGamma(){
return ((LayerSymbol) getElement())
.getBooleanValue(AllPredefinedLayers.FIX_GAMMA_NAME).get();
}
public int getNsize(){
return ((LayerSymbol) getElement())
.getIntValue(AllPredefinedLayers.NSIZE_NAME).get();
}
public double getKnorm(){
return ((LayerSymbol) getElement())
.getDoubleValue(AllPredefinedLayers.KNORM_NAME).get();
}
public double getAlpha(){
return ((LayerSymbol) getElement())
.getDoubleValue(AllPredefinedLayers.ALPHA_NAME).get();
}
public double getBeta(){
return ((LayerSymbol) getElement())
.getDoubleValue(AllPredefinedLayers.BETA_NAME).get();
}
@Nullable
public String getPoolType(){
return ((LayerSymbol) getElement())
.getStringValue(AllPredefinedLayers.POOL_TYPE_NAME).get();
}
@Nullable
public List<Integer> getPadding(){
return getPadding((LayerSymbol) getElement());
}
@Nullable
public List<Integer> getPadding(LayerSymbol layer){
List<Integer> kernel = layer.getIntTupleValue(AllPredefinedLayers.KERNEL_NAME).get();
List<Integer> stride = layer.getIntTupleValue(AllPredefinedLayers.STRIDE_NAME).get();
ArchTypeSymbol inputType = layer.getInputTypes().get(0);
ArchTypeSymbol outputType = layer.getOutputTypes().get(0);
int heightWithPad = kernel.get(0) + stride.get(0)*(outputType.getHeight() - 1);
int widthWithPad = kernel.get(1) + stride.get(1)*(outputType.getWidth() - 1);
int heightPad = Math.max(0, heightWithPad - inputType.getHeight());
int widthPad = Math.max(0, widthWithPad - inputType.getWidth());
int topPad = (int)Math.ceil(heightPad / 2.0);
int bottomPad = (int)Math.floor(heightPad / 2.0);
int leftPad = (int)Math.ceil(widthPad / 2.0);
int rightPad = (int)Math.floor(widthPad / 2.0);
if (topPad == 0 && bottomPad == 0 && leftPad == 0 && rightPad == 0){
return null;
}
return Arrays.asList(0,0,0,0,topPad,bottomPad,leftPad,rightPad);
}
}
......@@ -20,14 +20,13 @@
*/
package de.monticore.lang.monticar.cnnarch.mxnetgenerator;
import de.monticore.lang.monticar.cnnarch.CNNArchGenerator;
import de.monticore.lang.monticar.cnnarch.generator.ArchitectureSupportChecker;
import de.monticore.lang.monticar.cnnarch.generator.CNNArchGenerator;
import de.monticore.lang.monticar.cnnarch.generator.CNNArchSymbolCompiler;
import de.monticore.lang.monticar.cnnarch.generator.DataPathConfigParser;
import de.monticore.lang.monticar.cnnarch.generator.LayerSupportChecker;
import de.monticore.lang.monticar.cnnarch.generator.Target;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchitectureSymbol;
import de.monticore.lang.monticar.cnnarch.DataPathConfigParser;
import de.monticore.lang.monticar.cnnarch.mxnetgenerator.checker.AllowAllLayerSupportChecker;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.cmake.CMakeConfig;
import de.monticore.lang.monticar.generator.cmake.CMakeFindModule;
import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.symboltable.Scope;
import de.se_rwth.commons.logging.Log;
......@@ -36,33 +35,16 @@ import java.util.HashMap;
import java.util.Map;
public class CNNArch2MxNet extends CNNArchGenerator {
public CNNArch2MxNet() {
setGenerationTargetPath("./target/generated-sources-cnnarch/");
}
public void generate(Scope scope, String rootModelName){
CNNArchSymbolCompiler symbolCompiler = new CNNArchSymbolCompiler(new AllowAllLayerSupportChecker());
ArchitectureSymbol architectureSymbol = symbolCompiler.compileArchitectureSymbol(scope, rootModelName);
try{
String confPath = getModelsDirPath() + "/data_paths.txt";
DataPathConfigParser newParserConfig = new DataPathConfigParser(confPath);
String dataPath = newParserConfig.getDataPath(rootModelName);
architectureSymbol.setDataPath(dataPath);
architectureSymbol.setComponentName(rootModelName);
generateFiles(architectureSymbol);
} catch (IOException e){
Log.error(e.toString());
}
public CNNArch2MxNet() {
architectureSupportChecker = new CNNArch2MxNetArchitectureSupportChecker();
layerSupportChecker = new CNNArch2MxNetLayerSupportChecker();
}
//check cocos with CNNArchCocos.checkAll(architecture) before calling this method.
public Map<String, String> generateStrings(ArchitectureSymbol architecture){
TemplateConfiguration templateConfiguration = new MxNetTemplateConfiguration();
Map<String, String> fileContentMap = new HashMap<>();
CNNArch2MxNetTemplateController archTc
= new CNNArch2MxNetTemplateController(architecture, templateConfiguration);
CNNArch2MxNetTemplateController archTc = new CNNArch2MxNetTemplateController(architecture);
Map.Entry<String, String> temp;
temp = archTc.process("CNNPredictor", Target.CPP);
......@@ -77,32 +59,6 @@ public class CNNArch2MxNet extends CNNArchGenerator {
temp = archTc.process("CNNBufferFile", Target.CPP);
fileContentMap.put("CNNBufferFile.h", temp.getValue());
checkValidGeneration(architecture);
return fileContentMap;
}
public void generateFromFilecontentsMap(Map<String, String> fileContentMap) throws IOException {
GeneratorCPP genCPP = new GeneratorCPP();
genCPP.setGenerationTargetPath(getGenerationTargetPath());
for (String fileName : fileContentMap.keySet()){
genCPP.generateFile(new FileContent(fileContentMap.get(fileName), fileName));
}
}
public Map<String, String> generateCMakeContent(String rootModelName) {
// model name should start with a lower case letter. If it is a component, replace dot . by _
rootModelName = rootModelName.replace('.', '_').replace('[', '_').replace(']', '_');
rootModelName = rootModelName.substring(0, 1).toLowerCase() + rootModelName.substring(1);
CMakeConfig cMakeConfig = new CMakeConfig(rootModelName);
cMakeConfig.addModuleDependency(new CMakeFindModule("Armadillo", true));
cMakeConfig.addCMakeCommand("set(LIBS ${LIBS} mxnet)");
Map<String,String> fileContentMap = new HashMap<>();
for (FileContent fileContent : cMakeConfig.generateCMakeFiles()){
fileContentMap.put(fileContent.getFileName(), fileContent.getFileContent());
}
return fileContentMap;
}
}
package de.monticore.lang.monticar.cnnarch.mxnetgenerator;
import de.monticore.lang.monticar.cnnarch.generator.ArchitectureSupportChecker;
public class CNNArch2MxNetArchitectureSupportChecker extends ArchitectureSupportChecker {
public CNNArch2MxNetArchitectureSupportChecker() {}
}
......@@ -19,7 +19,9 @@
* *******************************************************************************
*/
package de.monticore.lang.monticar.cnnarch.mxnetgenerator;
import de.monticore.lang.monticar.cnnarch.CNNArchGenerator;
import de.monticore.lang.monticar.cnnarch.generator.CNNArchGenerator;
import de.monticore.lang.monticar.cnnarch.generator.GenericCNNArchCli;
public class CNNArch2MxNetCli {
public static void main(String[] args) {
......
package de.monticore.lang.monticar.cnnarch.mxnetgenerator;
import de.monticore.lang.monticar.cnnarch.generator.LayerSupportChecker;
import de.monticore.lang.monticar.cnnarch.predefined.AllPredefinedLayers;
public class CNNArch2MxNetLayerSupportChecker extends LayerSupportChecker {
public CNNArch2MxNetLayerSupportChecker() {
supportedLayerList.add(AllPredefinedLayers.FULLY_CONNECTED_NAME);
supportedLayerList.add(AllPredefinedLayers.CONVOLUTION_NAME);
supportedLayerList.add(AllPredefinedLayers.SOFTMAX_NAME);
supportedLayerList.add(AllPredefinedLayers.SIGMOID_NAME);
supportedLayerList.add(AllPredefinedLayers.TANH_NAME);
supportedLayerList.add(AllPredefinedLayers.RELU_NAME);
supportedLayerList.add(AllPredefinedLayers.DROPOUT_NAME);
supportedLayerList.add(AllPredefinedLayers.POOLING_NAME);
supportedLayerList.add(AllPredefinedLayers.GLOBAL_POOLING_NAME);
supportedLayerList.add(AllPredefinedLayers.LRN_NAME);
supportedLayerList.add(AllPredefinedLayers.BATCHNORM_NAME);
supportedLayerList.add(AllPredefinedLayers.SPLIT_NAME);
supportedLayerList.add(AllPredefinedLayers.GET_NAME);
supportedLayerList.add(AllPredefinedLayers.ADD_NAME);
supportedLayerList.add(AllPredefinedLayers.CONCATENATE_NAME);
supportedLayerList.add(AllPredefinedLayers.FLATTEN_NAME);
supportedLayerList.add(AllPredefinedLayers.ONE_HOT_NAME);
}
}
package de.monticore.lang.monticar.cnnarch.mxnetgenerator;
import de.monticore.lang.monticar.cnnarch.generator.ArchitectureElementData;
import de.monticore.lang.monticar.cnnarch.generator.CNNArchTemplateController;
import de.monticore.lang.monticar.cnnarch._symboltable.*;
import java.io.Writer;
/**
*
*/
public class CNNArch2MxNetTemplateController extends CNNArchTemplateController {
public CNNArch2MxNetTemplateController(ArchitectureSymbol architecture,
TemplateConfiguration templateConfiguration) {
super(architecture, templateConfiguration);
public CNNArch2MxNetTemplateController(ArchitectureSymbol architecture) {
super(architecture, new MxNetTemplateConfiguration());
}
public void include(IOSymbol ioElement, Writer writer){
......@@ -60,7 +58,7 @@ public class CNNArch2MxNetTemplateController extends CNNArchTemplateController {
public void include(ArchitectureElementSymbol architectureElement, Writer writer){
if (architectureElement instanceof CompositeElementSymbol){
include((CompositeElementSymbol) architectureElement, writer);
} else if (architectureElement instanceof LayerSymbol){
} else if (architectureElement instanceof LayerSymbol) {
include((LayerSymbol) architectureElement, writer);
} else {
include((IOSymbol) architectureElement, writer);
......
......@@ -20,18 +20,8 @@
*/
package de.monticore.lang.monticar.cnnarch.mxnetgenerator;
//can be removed
public enum Target {
PYTHON{
@Override
public String toString() {
return ".py";
}
},
CPP{
@Override
public String toString() {
return ".h";
}
}
}
import de.monticore.lang.monticar.cnnarch.generator.TrainParamSupportChecker;
public class CNNArch2MxNetTrainParamSupportChecker extends TrainParamSupportChecker {
}
\ No newline at end of file
package de.monticore.lang.monticar.cnnarch.mxnetgenerator;
import de.monticore.io.paths.ModelPath;
import de.monticore.lang.monticar.cnnarch._cocos.CNNArchCocos;
import de.monticore.lang.monticar.cnnarch._symboltable.*;
import de.monticore.lang.monticar.cnnarch.mxnetgenerator.checker.LayerSupportChecker;
import de.monticore.symboltable.GlobalScope;
import de.monticore.symboltable.Scope;
import de.se_rwth.commons.logging.Log;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
public class CNNArchSymbolCompiler {
private final LayerSupportChecker layerChecker;
public CNNArchSymbolCompiler(final LayerSupportChecker layerChecker) {
this.layerChecker = layerChecker;
}
public ArchitectureSymbol compileArchitectureSymbolFromModelsDir(
final Path modelsDirPath, final String rootModel) {
ModelPath mp = new ModelPath(modelsDirPath);
GlobalScope scope = new GlobalScope(mp, new CNNArchLanguage());
return compileArchitectureSymbol(scope, rootModel);
}
public ArchitectureSymbol compileArchitectureSymbol(Scope scope, String rootModelName) {
Optional<CNNArchCompilationUnitSymbol> compilationUnit = scope.resolve(rootModelName, CNNArchCompilationUnitSymbol.KIND);
if (!compilationUnit.isPresent()){
failWithMessage("Could not resolve architecture " + rootModelName);
}
CNNArchCocos.checkAll(compilationUnit.get());
if (!supportCheck(compilationUnit.get().getArchitecture())){
failWithMessage("Architecture not supported by generator");
}
return compilationUnit.get().getArchitecture();
}
private void failWithMessage(final String message) {
Log.error(message);
System.exit(1);
}
private boolean supportCheck(ArchitectureSymbol architecture){
for (ArchitectureElementSymbol element : ((CompositeElementSymbol)architecture.getBody()).getElements()){
if(!isSupportedLayer(element, layerChecker)) {
return false;
}
}
return true;
}
private boolean isSupportedLayer(ArchitectureElementSymbol element, LayerSupportChecker layerChecker){
List<ArchitectureElementSymbol> constructLayerElemList;
if (element.getResolvedThis().get() instanceof CompositeElementSymbol) {
constructLayerElemList = ((CompositeElementSymbol)element.getResolvedThis().get()).getElements();
for (ArchitectureElementSymbol constructedLayerElement : constructLayerElemList) {
if (!isSupportedLayer(constructedLayerElement, layerChecker)) {
return false;
}
}
}
if (!layerChecker.isSupported(element.toString())) {
Log.error("Unsupported layer " + "'" + element.getName() + "'" + " for the backend.");
return false;
} else {
return true;
}
}
}
/**
*
* ******************************************************************************
* MontiCAR Modeling Family, www.se-rwth.de
* Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
* All rights reserved.
*
* This project is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package de.monticore.lang.monticar.cnnarch.mxnetgenerator;
import de.monticore.lang.monticar.cnnarch._symboltable.*;
import de.monticore.lang.monticar.cnnarch.predefined.Sigmoid;
import de.monticore.lang.monticar.cnnarch.predefined.Softmax;
import java.io.StringWriter;
import java.io.Writer;
import java.util.*;
public abstract class CNNArchTemplateController {
public static final String FTL_FILE_ENDING = ".ftl";
public static final String TEMPLATE_ELEMENTS_DIR_PATH = "elements/";
public static final String TEMPLATE_CONTROLLER_KEY = "tc";
public static final String ELEMENT_DATA_KEY = "element";
private final TemplateConfiguration templateConfiguration;
private LayerNameCreator nameManager;
private ArchitectureSymbol architecture;
//temporary attributes. They are set after calling process()
private Writer writer;
private String mainTemplateNameWithoutEnding;
private Target targetLanguage;
private ArchitectureElementData dataElement;
protected CNNArchTemplateController(ArchitectureSymbol architecture, TemplateConfiguration templateConfiguration) {
setArchitecture(architecture);
this.templateConfiguration = templateConfiguration;
}
protected TemplateConfiguration getTemplateConfiguration() {
return templateConfiguration;
}
protected LayerNameCreator getNameManager() {
return nameManager;
}
protected void setNameManager(LayerNameCreator nameManager) {
this.nameManager = nameManager;
}
protected Writer getWriter() {
return writer;
}
protected void setWriter(Writer writer) {
this.writer = writer;
}
protected String getMainTemplateNameWithoutEnding() {
return mainTemplateNameWithoutEnding;
}
protected void setMainTemplateNameWithoutEnding(String mainTemplateNameWithoutEnding) {
this.mainTemplateNameWithoutEnding = mainTemplateNameWithoutEnding;
}
protected Target getTargetLanguage() {
return targetLanguage;
}
protected void setTargetLanguage(Target targetLanguage) {
this.targetLanguage = targetLanguage;
}
protected ArchitectureElementData getDataElement() {
return dataElement;
}
protected void setDataElement(ArchitectureElementData dataElement) {
this.dataElement = dataElement;
}
public String getFileNameWithoutEnding() {
return mainTemplateNameWithoutEnding + "_" + getFullArchitectureName();
}
public ArchitectureElementData getCurrentElement() {
return dataElement;
}
public void setCurrentElement(ArchitectureElementSymbol layer) {
this.dataElement = new ArchitectureElementData(getName(layer), layer, this);
}
public void setCurrentElement(ArchitectureElementData dataElement) {
this.dataElement = dataElement;
}
public ArchitectureSymbol getArchitecture() {
return architecture;
}
public void setArchitecture(ArchitectureSymbol architecture) {
this.architecture = architecture;
this.nameManager = new LayerNameCreator(architecture);
}
public String getName(ArchitectureElementSymbol layer){
return nameManager.getName(layer);
}
public String getArchitectureName(){
return getArchitecture().getEnclosingScope().getSpanningSymbol().get().getName().replaceAll("\\.","_");
}
public String getFullArchitectureName(){
return getArchitecture().getEnclosingScope().getSpanningSymbol().get().getFullName().replaceAll("\\.","_");
}
public String getDataPath(){
return getArchitecture().getDataPath();
}
public List<String> getLayerInputs(ArchitectureElementSymbol layer){
List<String> inputNames = new ArrayList<>();
for (ArchitectureElementSymbol input : layer.getPrevious()) {