diff --git a/Grinder/Version.h b/Grinder/Version.h
index 9bc3062c581b981e052313e4fa9db36f7469fd81..68fff9b32e62ee66725ff9b519466e529eb77d6e 100644
--- a/Grinder/Version.h
+++ b/Grinder/Version.h
@@ -10,14 +10,14 @@
 
 #define GRNDR_INFO_TITLE		"Grinder"
 #define GRNDR_INFO_COPYRIGHT	"Copyright (c) WWU Muenster"
-#define GRNDR_INFO_DATE			"08.10.2019"
+#define GRNDR_INFO_DATE			"10.10.2019"
 #define GRNDR_INFO_COMPANY		"WWU Muenster"
 #define GRNDR_INFO_WEBSITE		"http://www.uni-muenster.de"
 
 #define GRNDR_VERSION_MAJOR		0
 #define GRNDR_VERSION_MINOR		15
 #define GRNDR_VERSION_REVISION	0
-#define GRNDR_VERSION_BUILD		400
+#define GRNDR_VERSION_BUILD		401
 
 namespace grndr
 {
diff --git a/Grinder/engine/data/DataType.cpp b/Grinder/engine/data/DataType.cpp
index 29a4fff16ede2ac8f7cb5c409763698e4dff59ad..d033251bd2a8c040562a96a76296755deb20e630 100644
--- a/Grinder/engine/data/DataType.cpp
+++ b/Grinder/engine/data/DataType.cpp
@@ -12,5 +12,4 @@ const char* DataType::Data = "Data";
 const char* DataType::ImageTags = "ImageTags";
 const char* DataType::GrabCutModels = "GrabCutModels";
 
-const char* DataType::MachineLearningMethod = "MachineLearningMethod";
-const char* DataType::MachineLearningState = "MachineLearningState";
+const char* DataType::MachineLearningModel = "MachineLearningModel";
diff --git a/Grinder/engine/data/DataType.h b/Grinder/engine/data/DataType.h
index eaae7a172839a3d920f533ec06a34169c23d8d89..1d0db3a50c83ec562fdf62efd3d72c720efa0f17 100644
--- a/Grinder/engine/data/DataType.h
+++ b/Grinder/engine/data/DataType.h
@@ -19,8 +19,7 @@ namespace grndr
 		static const char* ImageTags;
 		static const char* GrabCutModels;
 
-		static const char* MachineLearningMethod;
-		static const char* MachineLearningState;
+		static const char* MachineLearningModel;
 
 	public:
 		using QString::QString;
diff --git a/Grinder/ml/blocks/MachineLearningBlock.cpp b/Grinder/ml/blocks/MachineLearningBlock.cpp
index a7033a9c408df2d4aac9079f6d6ca689c13d8f8e..51a7802f6bdc4e730a8752fa1dad06576489b508 100644
--- a/Grinder/ml/blocks/MachineLearningBlock.cpp
+++ b/Grinder/ml/blocks/MachineLearningBlock.cpp
@@ -41,17 +41,14 @@ bool MachineLearningBlock::updateProperties(PropertyBase* updatedProp)
 
 void MachineLearningBlock::createPorts()
 {	
-	DataDescriptors methodPortDataDescs = {DataDescriptor::customDescriptor("Machine learning method", DataType::MachineLearningMethod)};
-	_methodPort = createPort(PortType::Method, Port::Direction::In, methodPortDataDescs, "Method");
-
-	DataDescriptors statePortDataDescs = {DataDescriptor::customDescriptor("Model state", DataType::MachineLearningState)};
-	_statePort = createPort(PortType::State, Port::Direction::In, statePortDataDescs, "State");
+	DataDescriptors inPortDataDescs = {DataDescriptor::imageDescriptor(true, DataDescriptor::ValueType::Any), DataDescriptor::imageDescriptor(false, DataDescriptor::ValueType::Any)};
+	_inPort = createPort(PortType::ImageIn, Port::Direction::In, inPortDataDescs, "In");
 
 	DataDescriptors imageTagsPortDataDescs = {DataDescriptor::customDescriptor("Image tags", DataType::ImageTags)};
 	_imageTagsPort = createPort(PortType::ImageTagsIn, Port::Direction::In, imageTagsPortDataDescs, "Tags");
 
-	DataDescriptors inPortDataDescs = {DataDescriptor::imageDescriptor(true, DataDescriptor::ValueType::Any), DataDescriptor::imageDescriptor(false, DataDescriptor::ValueType::Any)};
-	_inPort = createPort(PortType::ImageIn, Port::Direction::In, inPortDataDescs, "In");
+	DataDescriptors modelPortDataDescs = {DataDescriptor::customDescriptor("Machine learning model", DataType::MachineLearningModel)};
+	_modelPort = createPort(PortType::Model, Port::Direction::In, modelPortDataDescs, "Model");
 }
 
 void MachineLearningBlock::updateTileSizeProperty()
diff --git a/Grinder/ml/blocks/MachineLearningBlock.h b/Grinder/ml/blocks/MachineLearningBlock.h
index 6ffad1732b09dfb54510568386a6f5894601d94d..edf65b2dd2eacad17d80553e0dd122d716553e53 100644
--- a/Grinder/ml/blocks/MachineLearningBlock.h
+++ b/Grinder/ml/blocks/MachineLearningBlock.h
@@ -26,10 +26,8 @@ namespace grndr
 		auto tilingOverlap() { return dynamic_cast<UIntProperty*>(_tilingOverlap.get()); }
 		auto tilingOverlap() const { return dynamic_cast<const UIntProperty*>(_tilingOverlap.get()); }
 
-		Port* methodPort() { return _methodPort.get(); }
-		const Port* methodPort() const { return _methodPort.get(); }
-		Port* statePort() { return _statePort.get(); }
-		const Port* statePort() const { return _statePort.get(); }
+		Port* modelPort() { return _modelPort.get(); }
+		const Port* modelPort() const { return _modelPort.get(); }
 		Port* imageTagsPort() { return _imageTagsPort.get(); }
 		const Port* imageTagsPort() const { return _imageTagsPort.get(); }
 		Port* inPort() { return _inPort.get(); }
@@ -48,8 +46,7 @@ namespace grndr
 		std::shared_ptr<PropertyBase> _tilingSize;
 		std::shared_ptr<PropertyBase> _tilingOverlap;
 
-		std::shared_ptr<Port> _methodPort;
-		std::shared_ptr<Port> _statePort;
+		std::shared_ptr<Port> _modelPort;
 		std::shared_ptr<Port> _imageTagsPort;
 		std::shared_ptr<Port> _inPort;
 	};
diff --git a/Grinder/ml/blocks/MachineLearningMethodBlock.h b/Grinder/ml/blocks/MachineLearningMethodBlock.h
index b910de4b8cc895e04eda78f1655f7e2bf6515203..e166840a4979242ac59f7e37c051370f4e6727fb 100644
--- a/Grinder/ml/blocks/MachineLearningMethodBlock.h
+++ b/Grinder/ml/blocks/MachineLearningMethodBlock.h
@@ -40,10 +40,8 @@ namespace grndr
 		auto state() { return dynamic_cast<MachineLearningStateProperty*>(_state.get()); }
 		auto state() const { return dynamic_cast<const MachineLearningStateProperty*>(_state.get()); }		
 
-		Port* methodPort() { return _methodPort.get(); }
-		const Port* methodPort() const { return _methodPort.get(); }
-		Port* statePort() { return _statePort.get(); }
-		const Port* statePort() const { return _statePort.get(); }
+		Port* modelPort() { return _modelPort.get(); }
+		const Port* modelPort() const { return _modelPort.get(); }
 
 	protected:
 		virtual void createProperties() override;
@@ -63,8 +61,7 @@ namespace grndr
 		std::shared_ptr<PropertyBase> _outputDirectory;
 		std::shared_ptr<PropertyBase> _state;
 
-		std::shared_ptr<Port> _methodPort;
-		std::shared_ptr<Port> _statePort;
+		std::shared_ptr<Port> _modelPort;
 	};
 }
 
diff --git a/Grinder/ml/blocks/MachineLearningMethodBlock.impl.h b/Grinder/ml/blocks/MachineLearningMethodBlock.impl.h
index caa8ecb04f020f79f39e42706d456fa4c87a3075..709a63a0ed7ce7f6ee1cffb169b17e8a374b192d 100644
--- a/Grinder/ml/blocks/MachineLearningMethodBlock.impl.h
+++ b/Grinder/ml/blocks/MachineLearningMethodBlock.impl.h
@@ -18,7 +18,7 @@ void MachineLearningMethodBlock<MethodType>::initBlock()
 {
 	Block::initBlock();
 
-	updateConfiguration();
+	updateConfiguration();	
 }
 
 template<typename MethodType>
@@ -52,8 +52,7 @@ bool MachineLearningMethodBlock<MethodType>::updateProperties(PropertyBase* upda
 
 	updateConfiguration();
 
-	if (updatedProp == _outputDirectory.get())
-		updated |= !this->checkStateAvailability();
+	updated |= !checkStateAvailability();
 
 	return updated;
 }
@@ -61,11 +60,8 @@ bool MachineLearningMethodBlock<MethodType>::updateProperties(PropertyBase* upda
 template<typename MethodType>
 void MachineLearningMethodBlock<MethodType>::createPorts()
 {	
-	DataDescriptors methodPortDataDescs = {DataDescriptor::customDescriptor("Machine learning method", DataType::MachineLearningMethod)};
-	_methodPort = createPort(PortType::Method, Port::Direction::Out, methodPortDataDescs, "Method");
-
-	DataDescriptors statePortDataDescs = {DataDescriptor::customDescriptor("Model state", DataType::MachineLearningState)};
-	_statePort = createPort(PortType::State, Port::Direction::Out, statePortDataDescs, "State");
+	DataDescriptors modelPortDataDescs = {DataDescriptor::customDescriptor("Machine learning model", DataType::MachineLearningModel)};
+	_modelPort = createPort(PortType::Model, Port::Direction::Out, modelPortDataDescs, "Model");
 }
 
 template<typename MethodType>
diff --git a/Grinder/ml/blocks/TrainingBlock.cpp b/Grinder/ml/blocks/TrainingBlock.cpp
index 105aac3f8e103365a5dcc3e4d75f40b142e190c6..bf3b249510b3ef30d377ec0de3236ae90e124261 100644
--- a/Grinder/ml/blocks/TrainingBlock.cpp
+++ b/Grinder/ml/blocks/TrainingBlock.cpp
@@ -24,5 +24,5 @@ void TrainingBlock::createPorts()
 {
 	MachineLearningBlock::createPorts();
 
-	_tagsBitmapPort = createPort(PortType::ImageTagsBitmap, Port::Direction::In, {DataDescriptor::imageDescriptor(false, DataDescriptor::ValueType::UInt32)}, "Tags bitmap");
+	_tagsBitmapPort = createPort(PortType::ImageTagsBitmap, Port::Direction::In, {DataDescriptor::imageDescriptor(false, DataDescriptor::ValueType::UInt32)}, "Tags bitmap", _modelPort);
 }
diff --git a/Grinder/ml/processors/InferenceProcessor.cpp b/Grinder/ml/processors/InferenceProcessor.cpp
index 27175a2e007b33069ebd569e32adeeb25e9b1939..9219fdd3fd75549b49a253d6ff9e205a20d3d7db 100644
--- a/Grinder/ml/processors/InferenceProcessor.cpp
+++ b/Grinder/ml/processors/InferenceProcessor.cpp
@@ -76,6 +76,14 @@ void InferenceProcessor::executionPass(EngineExecutionContext& ctx, const Machin
 	}
 }
 
+void InferenceProcessor::fillTaskData(EngineExecutionContext& ctx, MachineLearningTaskData& taskData) const
+{
+	MachineLearningProcessor::fillTaskData(ctx, taskData);
+
+	if (taskData.state.isEmpty())
+		throwProcessorException("A model state is required for performing inference");
+}
+
 void InferenceProcessor::forwardInferenceResults(EngineExecutionContext& ctx, const DataBlob* dataBlob, const MachineLearningTask::ImageInferenceResults& results, bool useCache) const
 {
 	QSize imgSize{dataBlob->getMatrix().cols, dataBlob->getMatrix().rows};
diff --git a/Grinder/ml/processors/InferenceProcessor.h b/Grinder/ml/processors/InferenceProcessor.h
index d4e64ce1d2dce63084f3b3aab1a8dc2a573955f4..a3b6457edc55ffb1086545e5691734308b59a847 100644
--- a/Grinder/ml/processors/InferenceProcessor.h
+++ b/Grinder/ml/processors/InferenceProcessor.h
@@ -22,6 +22,8 @@ namespace grndr
 		virtual void firstExecutionPass(EngineExecutionContext& ctx, const MachineLearningTaskData& taskData) override;
 		virtual void executionPass(EngineExecutionContext& ctx, const MachineLearningTaskData& taskData) override;
 
+		virtual void fillTaskData(EngineExecutionContext& ctx, MachineLearningTaskData& taskData) const override;
+
 	private:
 		void forwardInferenceResults(EngineExecutionContext& ctx, const DataBlob* dataBlob, const MachineLearningTask::ImageInferenceResults& results, bool useCache = true) const;
 	};
diff --git a/Grinder/ml/processors/MachineLearningMethodProcessor.impl.h b/Grinder/ml/processors/MachineLearningMethodProcessor.impl.h
index 67ae199d1612c0185686528ba7707af7b97dae98..93c012051f0fda2ef9804ca4012d1948bb836e21 100644
--- a/Grinder/ml/processors/MachineLearningMethodProcessor.impl.h
+++ b/Grinder/ml/processors/MachineLearningMethodProcessor.impl.h
@@ -29,7 +29,7 @@ void MachineLearningMethodProcessor<MethodType>::execute(EngineExecutionContext&
 		this->_block->method().config().verifyConfiguration();
 	}
 
-	// Store the machine learning method and model state in the context data
-	ctx.data().set(this->_block->methodPort(), Data_Value_Method, static_cast<const MachineLearningMethodBase*>(&this->_block->method()));
-	ctx.data().set(this->_block->statePort(), Data_Value_State, this->_block->state()->getValue());
+	// Store the machine learning method and state in the context data
+	ctx.data().set(this->_block->modelPort(), Data_Value_Method, static_cast<const MachineLearningMethodBase*>(&this->_block->method()));
+	ctx.data().set(this->_block->modelPort(), Data_Value_State, this->_block->state()->getValue());
 }
diff --git a/Grinder/ml/processors/MachineLearningProcessor.impl.h b/Grinder/ml/processors/MachineLearningProcessor.impl.h
index b4ef8b122e62094302c97b70f755fe82d540f273..e75646ada8bcc5df50eddc6219e94f5303c8c957 100644
--- a/Grinder/ml/processors/MachineLearningProcessor.impl.h
+++ b/Grinder/ml/processors/MachineLearningProcessor.impl.h
@@ -33,7 +33,7 @@ MachineLearningProcessor<BlockType>::MachineLearningProcessor(const Block* block
 template<typename BlockType>
 void MachineLearningProcessor<BlockType>::fillTaskData(EngineExecutionContext& ctx, MachineLearningTaskData& taskData) const
 {
-	taskData.method = this->template portData<const MachineLearningMethodBase*>(ctx, this->_block->methodPort(), Data_Value_Method);
+	taskData.method = this->template portData<const MachineLearningMethodBase*>(ctx, this->_block->modelPort(), Data_Value_Method);
 	taskData.imageTags = this->template portData<const ImageTags*>(ctx, this->_block->imageTagsPort(), ImageTagsProcessor::Data_Value_ImageTags);
 
 	if (auto dataBlob = this->portData(ctx, this->_block->inPort()))
@@ -46,7 +46,7 @@ void MachineLearningProcessor<BlockType>::fillTaskData(EngineExecutionContext& c
 		taskData.imageTiler = std::move(imageTiler);
 	}
 
-	taskData.state = this->template portData<QString>(ctx, this->_block->statePort(), Data_Value_State, false);
+	taskData.state = this->template portData<QString>(ctx, this->_block->modelPort(), Data_Value_State, false);
 }
 
 template<typename BlockType>
diff --git a/Grinder/pipeline/Block.cpp b/Grinder/pipeline/Block.cpp
index 3f31d1371a0769a19b2a3cfa5b1f1ca09520507d..0a3e3e126ab663fb876425636c18a615a6c72ac5 100644
--- a/Grinder/pipeline/Block.cpp
+++ b/Grinder/pipeline/Block.cpp
@@ -152,7 +152,7 @@ void Block::deserialize(DeserializationContext& ctx)
 	deserializePorts(ctx);
 }
 
-std::shared_ptr<Port> Block::createPort(PortType type, Port::Direction dir, DataDescriptors dataDescriptors, QString name)
+std::shared_ptr<Port> Block::createPort(PortType type, Port::Direction dir, DataDescriptors dataDescriptors, QString name, const std::shared_ptr<Port>& insertBefore)
 {
 	if (type == PortType::Undefined)
 		throw std::invalid_argument{_EXCPT("type may not be PortType::Undefined")};
@@ -169,7 +169,22 @@ std::shared_ptr<Port> Block::createPort(PortType type, Port::Direction dir, Data
 		throw;
 	}
 
-	_ports.push_back(port);
+	bool portAdded = false;
+
+	if (insertBefore)
+	{
+		auto it = std::find(_ports.cbegin(), _ports.cend(), insertBefore);
+
+		if (it != _ports.cend())
+		{
+			_ports.insert(it, port);
+			portAdded = true;
+		}
+	}
+
+	if (!portAdded)
+		_ports.push_back(port);
+
 	emit portsModified();
 
 	return port;
diff --git a/Grinder/pipeline/Block.h b/Grinder/pipeline/Block.h
index 8d2612078f8e86942914d1b389fcf4e888c9cd94..f553f0f49a4a55430af4efd701c9de6d2ff1beb0 100644
--- a/Grinder/pipeline/Block.h
+++ b/Grinder/pipeline/Block.h
@@ -78,7 +78,7 @@ namespace grndr
 	protected:
 		virtual void createPorts() = 0;
 
-		std::shared_ptr<Port> createPort(PortType type, Port::Direction dir, DataDescriptors dataDescriptors, QString name = "");
+		std::shared_ptr<Port> createPort(PortType type, Port::Direction dir, DataDescriptors dataDescriptors, QString name = "", const std::shared_ptr<Port>& insertBefore = nullptr);
 		void resetPort(Port* port, PortType newType, QString newName = "");
 		void removePort(PortType type);
 		void removePort(const Port* port);
diff --git a/Grinder/pipeline/PortType.cpp b/Grinder/pipeline/PortType.cpp
index 880a6a5e1a7b19b58b0fe406af44b3fd50eead7b..ad153cff4552318f53c343eb96b2f9c76e1e986a 100644
--- a/Grinder/pipeline/PortType.cpp
+++ b/Grinder/pipeline/PortType.cpp
@@ -28,6 +28,4 @@ const char* PortType::Markers = "Markers";
 const char* PortType::Predecessor = "Predecessor";
 const char* PortType::Successor = "Successor";
 
-const char* PortType::Method = "Method";
-const char* PortType::State = "State";
-const char* PortType::TrainedState = "TrainedState";
+const char* PortType::Model = "Model";
diff --git a/Grinder/pipeline/PortType.h b/Grinder/pipeline/PortType.h
index 07c92f3fcbadfca8fe6df7f0a3ffd60c596b44a4..4df12deeb403470ef1a2c0ffbfd0874845a57889 100644
--- a/Grinder/pipeline/PortType.h
+++ b/Grinder/pipeline/PortType.h
@@ -35,9 +35,7 @@ namespace grndr
 		static const char* Predecessor;
 		static const char* Successor;
 
-		static const char* Method;
-		static const char* State;
-		static const char* TrainedState;
+		static const char* Model;
 
 	public:
 		using QString::QString;