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;
}
}
}
c#常规梯度下降及其优化
最新推荐文章于 2024-05-21 17:31:17 发布