class CosineSimilarityVertex extends SameDiffLambdaVertex {
override def defineVertex(sameDiff: SameDiff, inputs: SameDiffLambdaVertex#VertexInputs): SDVariable = {
val x = inputs.getInput(0)
val y = inputs.getInput(1)
//calculate cosine similarity
val x_norm = x.norm2(-1)
val y_norm = y.norm2(-1)
val dot = sameDiff.sum(x.mul(y), -1)
dot.div(x_norm.mul(y_norm))
}
}
def createModel(numOutput: Int, numInput: Int, numActions: Int) = {
val conf = new NeuralNetConfiguration.Builder()
.seed(123)
.updater(new Nadam(0.0001))
.optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
.graphBuilder()
.addInputs("Features1", "Features2")
.addLayer("FeatureLayer1", new DenseLayer.Builder().activation(Activation.TANH).nIn(numInput).nOut(numInput*2).weightInit(WeightInit.XAVIER).build(), "Features1")
.addLayer("FeatureLayer2", new DenseLayer.Builder().activation(Activation.TANH).nIn(numInput*2).nOut(numOutput).weightInit(WeightInit.XAVIER).build(), "FeatureLayer1")
.addLayer("Embedding", new EmbeddingLayer.Builder().nIn(numActions).nOut(numOutput).build(), "Features2")
.addVertex("CosineSimilarity", new CosineSimilarityVertex(), "FeatureLayer2", "Embedding")
.setOutputs("CosineSimilarity")
.build()
val model = new ComputationGraph(conf)
model.init()
model
}
val feature1 = Nd4j.create(Array(1, 0.5, 1.0, 1.2, 0.2, 0.4, 0.5), Array(1, 7))
val feature2 = Nd4j.create(Array(1.0, 2.0, 0.0, 3.0), Array(4, 1)) //arbitrary size from 1->n
val model = createModel(2, 7, 4)
val prediction = model.output(false, feature1, feature2)
println(prediction(0))
[0.4629, 0.1703, 0.1670, 0.2561]
If I try to fit the network however, I get the following error:
println("Fitting...")
val combined: Array[INDArray] = Array(feature1, feature2)
val error = Array(Nd4j.create(Array(0.5, 0.2, 1.0, 0), Array(4, 1)))
model.fit(new MultiDataSet(combined, error))
Exception in thread "main" java.lang.NullPointerException
at org.deeplearning4j.nn.graph.ComputationGraph.calcBackpropGradients(ComputationGraph.java:2681)
at org.deeplearning4j.nn.graph.ComputationGraph.computeGradientAndScore(ComputationGraph.java:1382)
at org.deeplearning4j.nn.graph.ComputationGraph.computeGradientAndScore(ComputationGraph.java:1342)
at org.deeplearning4j.optimize.solvers.BaseOptimizer.gradientAndScore(BaseOptimizer.java:170)
at org.deeplearning4j.optimize.solvers.StochasticGradientDescent.optimize(StochasticGradientDescent.java:63)
at org.deeplearning4j.optimize.Solver.optimize(Solver.java:52)
at org.deeplearning4j.nn.graph.ComputationGraph.fitHelper(ComputationGraph.java:1166)
at org.deeplearning4j.nn.graph.ComputationGraph.fit(ComputationGraph.java:1116)
at org.deeplearning4j.nn.graph.ComputationGraph.fit(ComputationGraph.java:1026)
at ai.decisive.nntesting.NNTesting$.main(NNTesting.scala:67)
at ai.decisive.nntesting.NNTesting.main(NNTesting.scala)
I took a look at the stacktrace and it seems to be because there is no Output layer defined. The issue is that I cannot have an output layer of a fixed size because the feature2 input is of variable size. So if there are 3 values in feature2, the output should be [1, 3]. Is there a way to have a variable size output layer in dl4j so that the model can be fitted?