微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将委托模式用于矩阵

如何解决将委托模式用于矩阵

根据this,我实现了一个委托模式以隐藏要基准的线性代数库,请参阅:

public interface Matrix<M> {

    /**
     * Cols or this matrix
     *
     * @return columns
     */
    int rows();

    /**
     * Rows of this matrix
     *
     * @return rows
     */
    int cols();

    /**
     * Matrix multiplication,should throw if cols and rows do not match.
     * Contract is This X in,i.e. this_rows*this_cols X in_cols*in_rows
     *
     * @param otherMatrix right operand
     * @return new matrix multiplied
     */
    M multiply(M otherMatrix);

    /**
     * Multiply each element with this scalar
     *
     * @param scalar to multiply with
     * @return scaled with scalar
     */
    M multiply(double scalar);

    /**
     * Add in to this matrix
     *
     * @param in right operand
     * @return this + in
     */
    M add(M in);

    /**
     * Add in to all elements of this.
     *
     * @param in scalar operand
     * @return this.map(e - > e + in)
     */
    M add(double in);

    /**
     * Subtract in from all elements of this
     *
     * @param in scalar operand
     * @return this.map(e - > e - in);
     */
    M subtract(double in);

    /**
     * Substract in from this matrix
     *
     * @param in right operand
     * @return this[i][j] -= in[i][j]
     */
    M subtract(M in);

    /**
     * Divide all elements by in
     *
     * @param in scalar operand
     * @return in.map(e - > e / in);
     */
    M divide(double in);

    /**
     * Map this matrix to a double,useful for reduce or trace implementations
     *
     * @param mapping f: This -> double
     * @return a double value
     */
    double map(Function<M,Double> mapping);

    /**
     * Map each element with this function
     *
     * @param mapping f: Double -> Double each element
     * @return this.map(e - > mapping ( e));
     */
    M mapElements(Function<Double,Double> mapping);

    /**
     * Sum this matrix over all entries.
     *
     * @return sum of this
     */
    double sum();

    /**
     * Max of this matrix over all entries.
     *
     * @return max of this
     */
    double max();

    /**
     * Index along a column of max,should only be used for vectors.
     *
     * @return index of max
     */
    int argMax();

    /**
     * Transpose this matrix.
     *
     * @return transpose.
     */
    M transpose();

    enum MatrixType {
        VECTOR,SQUARE
    }
}

使用此类:

public class UJMPMatrix implements Matrix<UJMPMatrix> {
    
    private org.ujmp.core.Matrix delegate;        

    public UJMPMatrix(UJMPMatrix in) { this.delegate = in.delegate; }
    public UJMPMatrix(org.ujmp.core.Matrix in) { this.delegate = in; }
   
    public int rows() {
        return (int) this.delegate.getRowCount();
    }

    public int cols() {
        return (int) this.delegate.getColumnCount();
    }

    @Override
    public UJMPMatrix multiply(UJMPMatrix otherMatrix) {
        return new UJMPMatrix(this.delegate.mtimes(otherMatrix.delegate));
    }


    @Override
    public UJMPMatrix multiply(double scalar) {
        return new UJMPMatrix(this.delegate.times(scalar));
    }

    @Override
    public UJMPMatrix add(UJMPMatrix in) {
        return new UJMPMatrix(this.delegate.plus(in.delegate));
    }

    @Override
    public UJMPMatrix add(double in) {
        return new UJMPMatrix(this.delegate.plus(in));
    }

    @Override
    public UJMPMatrix subtract(double in) {
        return new UJMPMatrix(this.delegate.minus(in));
    }

    @Override
    public UJMPMatrix subtract(UJMPMatrix in) {
        return new UJMPMatrix(this.delegate.minus(in.delegate));
    }

    @Override
    public UJMPMatrix divide(double in) {
        return new UJMPMatrix(this.delegate.divide(in));
    }

    @Override
    public double map(Function<UJMPMatrix,Double> mapping) {
        return mapping.apply(this);
    }

    @Override
    public UJMPMatrix mapElements(Function<Double,Double> mapping) {
        double[][] elements = this.delegate.todoubleArray();
        double[][] out = new double[elements.length][elements[0].length];
        for (int i = 0; i < elements.length; i++) {
            for (int j = 0; j < elements[0].length; i++) {
                out[i][j] = mapping.apply(elements[i][j]);
            }
        }
        return new UJMPMatrix(out,rows(),cols());
    }

    @Override
    public double sum() {
        return this.delegate.getValueSum();
    }

    @Override
    public double max() {
        return this.delegate.max(Calculation.Ret.NEW,0).doubleValue();
    }

    @Override
    public UJMPMatrix transpose() {
        return new UJMPMatrix(this.delegate.transpose());
    }

    @Override
    public int argMax() {
        double[] array = this.delegate.todoubleArray()[0];
        int argMax = -1;
        double best = Double.MIN_VALUE;
        for (int i = 0; i < array.length; i++) {
            if (array[i] > best) {
                best = array[i];
                argMax = i;
            }
        }

        return argMax;

    }
}

但是,当我想使用这种抽象时,Java告诉我我不能使用任何这些方法,因为我需要使用通配符(?)来声明这些矩阵:

 private void FeedForward(final Matrix<? extends Matrix<?>> starter,final List<Matrix<? extends Matrix<?>>> actives) {
        Matrix<? extends Matrix<?>> toPredict = starter;

        actives.add(toPredict);
        for (int i = 0; i < this.totalLayers - 1; i++) {
            final Matrix<? extends Matrix<?>> x = this.weights[i].multiply(toPredict).add(this.biases[i]);
            // Weights and Biases are also Matrix<? extends Matrix<?>>[].
            // error: cannot resolve method multiply(Matrix<capture ? extends Matrix<?>>)
            toPredict = this.functions[i + 1].function(x);
            actives.add(toPredict);
        }
    }

注意:在神经网络的构造函数中,我让调用者通过一个简单的枚举{OJ_ALGO,UJMP}决定他们想要的矩阵类型,然后调用我实现的Factory初始化这些矩阵。神经网络的字段如下所示:

// Weights and biases of the network
private volatile Matrix<? extends Matrix<?>>[] weights;
private volatile Matrix<? extends Matrix<?>>[] biases;
private volatile Matrix<? extends Matrix<?>>[] dW;
private volatile Matrix<? extends Matrix<?>>[] dB;

问题:如何声明,初始化和利用我在此神经网络库中实现的矩阵抽象?

解决方法

您的feedForward方法需要一个通用类型来表示两个参数必须具有相同的类型(请注意<M>在void之前):

private <M> void feedForward(final Matrix<M> starter,final List<M> actives) {

同样,您的神经网络类应声明其使用的矩阵类型(假设您不想同时使用不同的实现):

public class NeuralNetwork<M> {
    private volatile Matrix<M>[] weights;
    private volatile Matrix<M>[] biases;
    private volatile Matrix<M>[] dW;
    private volatile Matrix<M>[] dB;

作为旁注,我不确定为什么将这些声明为易失性。

您的界面应如下所示:

public interface Matrix<M> {
    Matrix<M> multiply(Matrix<M> otherMatrix);
    M delegate();

以及您的实现:

public class UJMPMatrix implements Matrix<org.ujmp.core.Matrix> {
    
    private org.ujmp.core.Matrix delegate; 

    @Override
    public UJMPMatrix  multiply(Matrix<org.ujmp.core.Matrix> otherMatrix) {
        return new UJMPMatrix(this.delegate.mtimes(otherMatrix.delegate()));
    }

    @Override
    public org.ujmp.core.Matrix delegate() {
        return delegate();
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。