c#常规梯度下降及其优化

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;

namespace MulLinearRegression
{
    public class Perceptron
    {
        /// <summary>
        /// 梯度下降类型
        /// </summary>
        public enum DescType
        {
            BATCH_GRAD_DESC,//
            STOCH_GRAD_DESC,
            MINI_BATCH_GRAD_DESC,
            MOMENTUM_GRAD_DESC,
            ADAGRAD,
            RMSProp,
            ADAM,
        }
        public static int Sign(double x)
        {
            return x > 0 ? 1 : x == 0 ? 0 : -1;
        }

        /// <summary>
        /// 感知机
        /// </summary>
        /// <param name="DataSet"></param>
        /// <param name="Labels"></param>
        /// <param name="Params">
        /// [lr]={BGD,SGD}
        /// [lr,batchSize]={MBGD}
        /// [lr,beta(0.5,0.99)]={MOMENTUM}
        /// [lr,epsilon]={ADAGRAD}
        /// [beta1,beta2]={ADAM}
        /// </param>
        /// <param name="Iterations"></param>
        /// <param name="GDType"></param>
        /// <returns></returns>
        public static double[,] PerceptronModel(double[,] DataSet, double[,] Labels, double[] Params, 
            double Iterations = 1e4,DescType GDType=DescType.ADAM)
        {
            int p = DataSet.GetLength(1);
            int n = DataSet.GetLength(0);
            double[,] weights = new double[p, 1];
            double[,] v = new double[p, 1];//momentum->v;adagrad->s
            double[,] s = new double[p, 1];//adam
            int check = -1;
            int t = (int)Iterations;
            while(((GDType != DescType.STOCH_GRAD_DESC) ? check != 0 : true) && t>=0)
            {
                double[,] shuffled = Matrix.MatrixCombine(Labels, DataSet, false);
                Matrix.MatrixShuffle(shuffled, out shuffled);
                double[,] shedLabels = Matrix.SubMatrix(shuffled, 0);
                shuffled = Matrix.MatrixRemoveVector(shuffled, 0);
                check = 0;
                switch (GDType)
                {
                    case DescType.BATCH_GRAD_DESC:
                        {
                            for(int i = 0; i < n; i++)
                            {
                                double[,] cx = Matrix.SubMatrix(shuffled, i, RowGet: true);
                                double preY = Matrix.MultiplyMatrix(cx, weights)[0, 0];
                                double signY = Sign(preY);
                                if (-signY * shedLabels[i, 0] >= 0)
                                {
                                    check += 1;
                                    double[,] lossGrad = Matrix.MultiplyConst(cx, Params[0] * shedLabels[i, 0]);
                                    weights = Matrix.AddMatrix(weights, Matrix.Transpose(lossGrad));
                                }
                            }
                            break;
                        }
                    case DescType.STOCH_GRAD_DESC: 
                        {
                            int rID = new Random().Next(n);
                            double[,] cx = Matrix.SubMatrix(shuffled, rID, RowGet: true);
                            double preY = Matrix.MultiplyMatrix(cx, weights)[0, 0];
                            if (-preY * shedLabels[rID, 0] >= 0)
                            {
                                double[,] lossGrad = Matrix.MultiplyConst(cx, shedLabels[rID, 0] * Params[0]);
                                weights = Matrix.AddMatrix(weights, Matrix.Transpose(lossGrad));
                                break;
                            }
                            else
                            {
                                break;
                            }
                        }
                    case DescType.MINI_BATCH_GRAD_DESC:
                        {
                            int rID = new Random().Next(n - (int)Params[1]);
                            for(int i = rID; i < rID + Params[1]; i++)
                            {
                                double[,] cx = Matrix.SubMatrix(shuffled, i, RowGet: true);
                                double preY = Matrix.MultiplyMatrix(cx, weights)[0, 0];
                                if (-preY * shedLabels[i, 0] < 0) continue;
                                check += 1;
                                double[,] lossGrad = Matrix.MultiplyConst(cx, Params[0] * shedLabels[i, 0]);
                                weights = Matrix.AddMatrix(weights, Matrix.Transpose(lossGrad));
                            }
                            break;
                        }
                    case DescType.MOMENTUM_GRAD_DESC:
                        {
                            double lr = Params[0];
                            double beta = Params[1];
                            int rID = new Random().Next(n - (int)Params[2]);
                            for (int i = rID; i < rID + Params[2]; i++)
                            {
                                double[,] cx = Matrix.SubMatrix(shuffled, i, RowGet: true);
                                double preY = Matrix.MultiplyMatrix(cx, weights)[0, 0];
                                if (-preY * shedLabels[i, 0] < 0) continue;
                                check += 1;
                                double[,] lossGrad = Matrix.MultiplyConst(cx, shedLabels[i, 0]);
                                v = Matrix.MultiplyConst(v, beta);
                                lossGrad = Matrix.MultiplyConst(lossGrad, 1 - beta);
                                v = Matrix.MultiplyConst(Matrix.AddMatrix(v, Matrix.Transpose(lossGrad)),lr);
                                weights = Matrix.AddMatrix(weights, v);
                            }
                            break;
                        }
                    case DescType.ADAGRAD:
                        {
                            double lr = Params[0];
                            double epsilon = Params[1];
                            int rID = new Random().Next(n - (int)Params[2]);
                            for (int i = rID; i < rID + Params[2]; i++)
                            {
                                double[,] cx = Matrix.SubMatrix(shuffled, i, RowGet: true);
                                double preY = Matrix.MultiplyMatrix(cx, weights)[0, 0];
                                if (-preY * shedLabels[i, 0] < 0) continue;
                                check += 1;
                                double[,] lossGrad = Matrix.MultiplyConst(cx, shedLabels[i, 0]);//行向量
                                double[,] lossGradSqua = Matrix.HadamardProduct(lossGrad, lossGrad);
                                s = Matrix.AddMatrix(s, Matrix.Transpose(lossGradSqua));//列向量
                                double[,] temp = Matrix.AddMatrix(Matrix.MatrixElementSqrt(s),Matrix.VectorGenerate(p,epsilon,false));//列向量
                                temp = Matrix.MultiplyConst(Matrix.MatrixElementReciprocal(temp), lr);//列向量
                                double[,] back = Matrix.HadamardProduct(temp, Matrix.Transpose(lossGrad));//列向量
                                weights = Matrix.AddMatrix(weights, back);
                            }
                            break;
                        }
                    case DescType.RMSProp:
                        {
                            double lr = Params[0];
                            double beta = Params[1];
                            double epsilon = Params[2];
                            int rID = new Random().Next(n - (int)Params[3]);
                            for (int i = rID; i < rID + Params[3]; i++)
                            {
                                double[,] cx = Matrix.SubMatrix(shuffled, i, RowGet: true);
                                double preY = Matrix.MultiplyMatrix(cx, weights)[0, 0];
                                if (-preY * shedLabels[i, 0] < 0) continue;
                                check += 1;
                                double[,] lossGrad = Matrix.MultiplyConst(cx, shedLabels[i, 0]);//行向量
                                //列向量
                                double[,] lossGradSqua = Matrix.HadamardProduct(lossGrad,lossGrad);
                                s = Matrix.MultiplyConst(s, beta);//列向量
                                lossGradSqua = Matrix.MultiplyConst(lossGradSqua, 1 - beta);
                                s = Matrix.AddMatrix(s, Matrix.Transpose(lossGradSqua));
                                double[,] sSqrt = Matrix.MatrixElementSqrt(s);
                                sSqrt = Matrix.AddMatrix(sSqrt,Matrix.VectorGenerate(p,epsilon,RowVec:false));
                                sSqrt = Matrix.MatrixElementReciprocal(sSqrt);
                                sSqrt = Matrix.MultiplyConst(sSqrt, lr);
                                sSqrt = Matrix.HadamardProduct(sSqrt, Matrix.Transpose(lossGrad));
                                weights = Matrix.AddMatrix(weights, sSqrt);
                            }
                            break;
                        }
                    case DescType.ADAM:
                        {
                            double lr = Params[0];
                            double beta1 = Params[1];
                            double beta2 = Params[2];
                            double epsilon = Params[3];
                            int rID = new Random().Next(n - (int)Params[4]);
                            for (int i = rID; i < rID + Params[4]; i++)
                            {
                                double[,] cx = Matrix.SubMatrix(shuffled, i, RowGet: true);
                                double preY = Matrix.MultiplyMatrix(cx, weights)[0, 0];
                                if (-preY * shedLabels[i, 0] < 0) continue;
                                check += 1;
                                double[,] lossGrad = Matrix.MultiplyConst(cx, shedLabels[i, 0]);//行向量
                                //列向量
                                double[,] lossGradSqua = Matrix.Transpose(Matrix.HadamardProduct(lossGrad, lossGrad));


                                v = Matrix.MultiplyConst(v, beta1);
                                double[,] vback = Matrix.MultiplyConst(lossGrad, 1 - beta1);
                                v = Matrix.AddMatrix(v, Matrix.Transpose(vback));

                                s = Matrix.MultiplyConst(s, beta2);//列向量
                                lossGradSqua = Matrix.MultiplyConst(lossGradSqua, 1 - beta2);
                                s = Matrix.AddMatrix(s, lossGradSqua);
                                double[,] sSqrt = Matrix.MatrixElementSqrt(s);
                                sSqrt = Matrix.AddMatrix(sSqrt, Matrix.VectorGenerate(p, epsilon, RowVec: false));
                                sSqrt = Matrix.MatrixElementReciprocal(sSqrt);
                                sSqrt = Matrix.MultiplyConst(sSqrt, lr);
                                sSqrt = Matrix.HadamardProduct(sSqrt, v);
                                weights = Matrix.AddMatrix(weights, sSqrt);
                            }
                            break;
                        }
                }
                t -= 1;
            }
            double[,] fRes = new double[Labels.GetLength(0), Labels.GetLength(1)];
            string[] result = new string[fRes.Length];
            for(int i = 0; i < fRes.GetLength(0); i++)
            {
                double ps = Matrix.MultiplyMatrix(Matrix.SubMatrix(DataSet, i, RowGet: true), weights)[0, 0];
                fRes[i, 0] = Sign(ps);
                result[i]=($"check:{fRes[i, 0]},Real:{Labels[i, 0]}");
            }
            return weights;
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值