DenseDoubleMatrix[] trainByInstance(DoubleVector trainingInstance)
throws Exception {
// initialize weight update matrices
DenseDoubleMatrix[] weightUpdateMatrices = new DenseDoubleMatrix[this.layerSizeArray.length - 1];
for (int m = 0; m < weightUpdateMatrices.length; ++m) {
weightUpdateMatrices[m] = new DenseDoubleMatrix(
this.layerSizeArray[m] + 1, this.layerSizeArray[m + 1]);
}
if (trainingInstance == null) {
return weightUpdateMatrices;
}
// transform the features (exclude the labels) to new space
double[] trainingVec = trainingInstance.toArray();
double[] trainingFeature = this.featureTransformer.transform(
trainingInstance.sliceUnsafe(0, this.layerSizeArray[0] - 1)).toArray();
double[] trainingLabels = Arrays.copyOfRange(trainingVec,
this.layerSizeArray[0], trainingVec.length);
DoubleVector trainingFeatureVec = new DenseDoubleVector(trainingFeature);
List<double[]> outputCache = this.outputInternal(trainingFeatureVec);
// calculate the delta of output layer
double[] delta = new double[this.layerSizeArray[this.layerSizeArray.length - 1]];
double[] outputLayerOutput = outputCache.get(outputCache.size() - 1);
double[] lastHiddenLayerOutput = outputCache.get(outputCache.size() - 2);
DenseDoubleMatrix prevWeightUpdateMatrix = this.prevWeightUpdateMatrices[this.prevWeightUpdateMatrices.length - 1];
for (int j = 0; j < delta.length; ++j) {
delta[j] = this.costFunction.applyDerivative(trainingLabels[j],
outputLayerOutput[j]);
// add regularization term
if (this.regularization != 0.0) {
double derivativeRegularization = 0.0;
DenseDoubleMatrix weightMatrix = this.weightMatrice[this.weightMatrice.length - 1];
for (int k = 0; k < this.layerSizeArray[this.layerSizeArray.length - 1]; ++k) {
derivativeRegularization += weightMatrix.get(k, j);
}
derivativeRegularization /= this.layerSizeArray[this.layerSizeArray.length - 1];
delta[j] += this.regularization * derivativeRegularization;
}