private void compute()
    {
        double[] weights = model.getWeights();
        double wscale = model.getWscale();
        // Unlike the C++ code in sgd, we would like to be RAII
        assert (u == null && b == null);
        int nPos = sequence.length();

        u = new double[nPos][numLabels];
        for (int pos = 0; pos < nPos; ++pos)
        {
            // For each feature from the sequence at position pos
            for (Offset offset : sequence.getOffsetsForU(pos))
            {
                int l = offset.index;
                for (int y = 0; y < numLabels; ++y, ++l)
                {
                    // Really tentative.  Right now weights is actually
                    // a matrix of FVxL, which is why this looks funny
                    // This is the total score for outcome y at position pos for unigram features
                    double acc = weights[l] * offset.value;
                    u[pos][y] += acc;
                }
            }

            CollectionsManip.scaleInplace(u[pos], wscale);

        }

        // First dimension is the last position
        // Second dimension is label
        // Third is the last label
        b = new double[nPos-1][numLabels][numLabels];
        for (int pos = 0; pos < nPos-1; ++pos)
        {
            for (Offset offset : sequence.getOffsetsForB(pos))
            {

                int l = offset.index;

                for (int yi = 0; yi < numLabels; ++yi)
                {
                    for (int yj = 0; yj < numLabels; ++yj, ++l)
                    {
                        double acc = weights[l] * offset.value;
                        b[pos][yi][yj] += acc;
                    }
                }
            }
            CollectionsManip.scaleInplace(b[pos], wscale);

        }
    }