78 строки
3.1 KiB
C#
78 строки
3.1 KiB
C#
// Copyright (c) Microsoft Corporation.
|
||
// Licensed under the MIT license.
|
||
|
||
using System;
|
||
using HEWrapper;
|
||
using MathNet.Numerics.LinearAlgebra;
|
||
|
||
namespace NeuralNetworks
|
||
{
|
||
public class LLPackedDenseLayer : BaseLayer
|
||
{
|
||
double[] _Weights = null;
|
||
public double[] Weights { get { return _Weights; } set { _Weights = value; layerPrepared = false; } }
|
||
double[] _Bias = null;
|
||
public double[] Bias { get { return _Bias; } set { _Bias = value; layerPrepared = false; } }
|
||
public double WeightsScale { get; set; } = 1.0;
|
||
|
||
public ulong PackingCount { get; set; } = 1;
|
||
public int PackingShift { get; set; } = 0;
|
||
|
||
public override double GetOutputScale()
|
||
{
|
||
return WeightsScale * Source.GetOutputScale();
|
||
}
|
||
|
||
IMatrix WeightsMatrix = null;
|
||
IMatrix BiasMatrix = null;
|
||
|
||
public override void Dispose()
|
||
{
|
||
if (WeightsMatrix != null) WeightsMatrix.Dispose();
|
||
if (BiasMatrix != null) BiasMatrix.Dispose();
|
||
WeightsMatrix = null;
|
||
BiasMatrix = null;
|
||
}
|
||
|
||
public override void Prepare()
|
||
{
|
||
if (layerPrepared) return;
|
||
int maps = Bias.Length;
|
||
int mapLength = Weights.Length / Bias.Length;
|
||
////////////////////////////
|
||
var ColumnWeightMatrix = Matrix<Double>.Build.DenseOfRowMajor(Bias.Length, Weights.Length / Bias.Length, Weights);
|
||
var NewRowsCount = (int)((maps + (int)PackingCount - 1) / (int)PackingCount);
|
||
var StackedMatrix = Matrix<double>.Build.Dense(NewRowsCount, (int)PackingCount * PackingShift);
|
||
var PaddedBias = Matrix<double>.Build.Dense(NewRowsCount, (int)PackingCount * PackingShift);
|
||
for (int i = 0; i < maps; i++)
|
||
{
|
||
int col = i % (int)PackingCount;
|
||
int row = i / (int)PackingCount;
|
||
var mat = Matrix<double>.Build.DenseOfRowVectors(new Vector<double>[] { ColumnWeightMatrix.Row(i) });
|
||
StackedMatrix.SetSubMatrix(row, col * PackingShift, mat);
|
||
PaddedBias[row, (col + 1) * PackingShift - 1] = Bias[i];
|
||
}
|
||
|
||
BiasMatrix = Factory.GetPlainMatrix(PaddedBias, EMatrixFormat.RowMajor, Source.GetOutputScale() * WeightsScale);
|
||
WeightsMatrix = Factory.GetPlainMatrix(StackedMatrix, EMatrixFormat.RowMajor, WeightsScale);
|
||
}
|
||
public override int OutputDimension()
|
||
{
|
||
return Bias.Length;
|
||
}
|
||
|
||
public override IMatrix Apply(IMatrix m)
|
||
{
|
||
if (m.ColumnCount > 1) throw new Exception("Expecting only one column");
|
||
IVector[] res = new IVector[WeightsMatrix.RowCount];
|
||
var vector = m.GetColumn(0);
|
||
ParallelProcessInEnv(res.Length, (env, task, k) =>
|
||
{
|
||
using (var mul = WeightsMatrix.GetRow(k).DotProduct(vector, (ulong)PackingShift, env))
|
||
res[k] = mul.Add(BiasMatrix.GetRow(k), env);
|
||
});
|
||
return Factory.GetMatrix(res, EMatrixFormat.ColumnMajor, CopyVectors: false);
|
||
}
|
||
}
|
||
}
|