this.alpha = alpha;
this.weights = new SparseDoubleRowMatrix(numFeatures, numOutcomes);
}
public void train(Iterable<Tuple<DoubleVector, DoubleVector>> dataStream) {
DoubleMatrix theta = this.weights;
initWeights(dataStream, theta);
for (int epoch = 0; epoch < epochs; epoch++) {
double lossSum = 0d;
int localItems = 0;
for (Tuple<DoubleVector, DoubleVector> tuple : dataStream) {
localItems++;
DoubleVector feature = tuple.getFirst();
DoubleVector outcome = tuple.getSecond();
DoubleVector z1 = theta.multiplyVectorColumn(feature);
DoubleVector activations = SIGMOID.apply(z1);
double loss = LOSS.calculateError(
new SparseDoubleRowMatrix(Arrays.asList(outcome)),
new SparseDoubleRowMatrix(Arrays.asList(activations)));
lossSum += loss;
DoubleVector activationDifference = activations.subtract(outcome);
// update theta by a smarter sparsity algorithm
Iterator<DoubleVectorElement> featureIterator = feature
.iterateNonZero();
while (featureIterator.hasNext()) {
DoubleVectorElement next = featureIterator.next();
DoubleVector rowVector = theta.getRowVector(next.getIndex());
double l2 = rowVector.pow(2d).sum();
Iterator<DoubleVectorElement> diffIterator = activationDifference
.iterateNonZero();
while (diffIterator.hasNext()) {
DoubleVectorElement diffElement = diffIterator.next();