public static cnn_net cnntrain(cnn_net net,double[][][] train_x,double[][] train_y,cnn_opt opt){
        int m = train_x.length;

        if((m % opt.batchsize) != 0){
            System.out.println("numbatches not integer");
            return null;
        }
        int numbatches = m/opt.batchsize;
        double[][][] x = new double[m][][];
        double[][] y = new double[m][];
        System.arraycopy(train_x,0,x,0,m);
        System.arraycopy(train_y,0,y,0,m);
        y = util.transpose(y);


        net.rL = null;

        for(int i = 0; i < opt.numepochs; i++){
            System.out.println("epoch "+(i+1)+"/"+opt.numepochs);

            int[]kk = util.randperm(m);

            for(int l = 0; l<numbatches; l++){
                int[] partKK = new int[opt.batchsize];
                System.arraycopy(kk,l* opt.batchsize,partKK,0,opt.batchsize);
                double[][][] batch_x = util.copyArray(x,partKK);

                double[][] batch_y = new double[y.length][opt.batchsize];
                for(int y1 =0;y1<y.length;y1++){
                    for(int y2=0;y2<opt.batchsize;y2++){
                        batch_y[y1][y2] = y[y1][partKK[y2]];
                    }
                }

                net = cnnff(net,batch_x);
                net = cnnbp(net,batch_y);
                net = cnnapplygrads(net,opt);
                if(net.rL==null){
                    net.rL =new double[1];
                    net.rL[0] = net.L;
                }
                double[] tmp = net.rL;
                net.rL = new double[tmp.length+1];
                for(int k=0;k<net.rL.length-1;k++){
                    net.rL[k]=tmp[k];
                }
                net.rL[net.rL.length-1] = 0.99*net.rL[net.rL.length-2]+0.01*net.L;
            }
        }
        return net;
    }