1+ using AiDotNet . Tensors . Helpers ;
2+
13namespace AiDotNet . TimeSeries ;
24
35/// <summary>
@@ -467,6 +469,23 @@ public Vector<T> ForecastHorizon(Vector<T> input)
467469 /// Embeds input time series into embedding space.
468470 /// Each time step is projected from scalar to embedding dimension.
469471 /// </summary>
472+ /// <param name="input">The input time series vector.</param>
473+ /// <returns>A list of embedding vectors, one per time step.</returns>
474+ /// <remarks>
475+ /// <para>
476+ /// <b>Input Length Handling:</b>
477+ /// The input is adjusted to match the configured LookbackWindow size:
478+ /// - If input.Length > LookbackWindow: Only the first LookbackWindow elements are used.
479+ /// This truncation is intentional as Informer uses a fixed encoder length for efficiency.
480+ /// - If input.Length < LookbackWindow: Zero-padding is added at the beginning (left-padding)
481+ /// to reach the required length.
482+ /// </para>
483+ /// <para><b>For Beginners:</b> The model needs a fixed-length input to work efficiently.
484+ /// If you provide more data than the lookback window, the extra oldest data points are ignored.
485+ /// If you provide less data, zeros are added at the start. For best results, provide exactly
486+ /// LookbackWindow data points.
487+ /// </para>
488+ /// </remarks>
470489 private List < Vector < T > > EmbedSequence ( Vector < T > input )
471490 {
472491 var embedded = new List < Vector < T > > ( ) ;
@@ -824,6 +843,7 @@ internal class InformerEncoderLayer<T>
824843 private readonly int _numHeads ;
825844 private readonly int _headDim ;
826845 private readonly int _sparsityFactor ;
846+ private readonly Random _random ;
827847
828848 // Multi-head attention weights (Q, K, V projections)
829849 private Matrix < T > _queryProj ;
@@ -855,12 +875,13 @@ internal class InformerEncoderLayer<T>
855875 public InformerEncoderLayer ( int embeddingDim , int numHeads , int sparsityFactor , double dropoutRate , int seed = 42 )
856876 {
857877 _numOps = MathHelper . GetNumericOperations < T > ( ) ;
878+ _random = RandomHelper . CreateSeededRandom ( seed ) ;
858879 _embeddingDim = embeddingDim ;
859880 _numHeads = numHeads ;
860881 _headDim = embeddingDim / numHeads ;
861882 _sparsityFactor = sparsityFactor ;
862883
863- var random = new Random ( seed ) ;
884+ var random = RandomHelper . CreateSeededRandom ( seed ) ;
864885 double attnStddev = Math . Sqrt ( 2.0 / embeddingDim ) ;
865886 double ffnStddev = Math . Sqrt ( 2.0 / ( embeddingDim * 4 ) ) ;
866887
@@ -887,6 +908,7 @@ public InformerEncoderLayer(int embeddingDim, int numHeads, int sparsityFactor,
887908 private InformerEncoderLayer ( )
888909 {
889910 _numOps = MathHelper . GetNumericOperations < T > ( ) ;
911+ _random = RandomHelper . CreateSeededRandom ( 42 ) ;
890912 _embeddingDim = 0 ;
891913 _numHeads = 1 ;
892914 _headDim = 0 ;
@@ -1166,8 +1188,7 @@ private T DotProduct(Vector<T> a, Vector<T> b)
11661188 public void UpdateWeights ( Vector < T > input , T target , T learningRate , T epsilon , T twoEpsilon ,
11671189 Func < Vector < T > , T > predict , int sampleSize )
11681190 {
1169- // Update a random subset of weights using numerical gradients
1170- var random = new Random ( ) ;
1191+ // Update a random subset of weights using numerical gradients (using seeded Random for reproducibility)
11711192 var allMatrices = new [ ] { _queryProj , _keyProj , _valueProj , _outputProj , _ffn1 , _ffn2 } ;
11721193
11731194 foreach ( var matrix in allMatrices )
@@ -1177,7 +1198,7 @@ public void UpdateWeights(Vector<T> input, T target, T learningRate, T epsilon,
11771198
11781199 for ( int s = 0 ; s < actualSample ; s ++ )
11791200 {
1180- int flatIdx = random . Next ( totalWeights ) ;
1201+ int flatIdx = _random . Next ( totalWeights ) ;
11811202 int i = flatIdx / matrix . Columns ;
11821203 int j = flatIdx % matrix . Columns ;
11831204
@@ -1329,6 +1350,7 @@ private static Vector<T> DeserializeVector(BinaryReader reader, INumericOperatio
13291350internal class DistillingConv < T >
13301351{
13311352 private readonly INumericOperations < T > _numOps ;
1353+ private readonly Random _random ;
13321354 private Matrix < T > _convWeights ;
13331355 private Vector < T > _convBias ;
13341356 private readonly int _poolingFactor ;
@@ -1338,9 +1360,10 @@ internal class DistillingConv<T>
13381360 public DistillingConv ( int embeddingDim , int poolingFactor , int seed = 42 )
13391361 {
13401362 _numOps = MathHelper . GetNumericOperations < T > ( ) ;
1363+ _random = RandomHelper . CreateSeededRandom ( seed ) ;
13411364 _poolingFactor = poolingFactor ;
13421365
1343- var random = new Random ( seed ) ;
1366+ var random = RandomHelper . CreateSeededRandom ( seed ) ;
13441367 double stddev = Math . Sqrt ( 2.0 / embeddingDim ) ;
13451368
13461369 // 1D convolution weights (kernel size = 3, same embedding dim)
@@ -1355,6 +1378,7 @@ public DistillingConv(int embeddingDim, int poolingFactor, int seed = 42)
13551378 private DistillingConv ( )
13561379 {
13571380 _numOps = MathHelper . GetNumericOperations < T > ( ) ;
1381+ _random = RandomHelper . CreateSeededRandom ( 42 ) ;
13581382 _convWeights = new Matrix < T > ( 0 , 0 ) ;
13591383 _convBias = new Vector < T > ( 0 ) ;
13601384 _poolingFactor = 2 ;
@@ -1423,13 +1447,13 @@ public List<Vector<T>> Forward(List<Vector<T>> input)
14231447 public void UpdateWeights ( Vector < T > input , T target , T learningRate , T epsilon , T twoEpsilon ,
14241448 Func < Vector < T > , T > predict , int sampleSize )
14251449 {
1426- var random = new Random ( ) ;
1450+ // Use seeded Random for reproducibility
14271451 int totalWeights = _convWeights . Rows * _convWeights . Columns ;
14281452 int actualSample = Math . Min ( sampleSize , totalWeights ) ;
14291453
14301454 for ( int s = 0 ; s < actualSample ; s ++ )
14311455 {
1432- int flatIdx = random . Next ( totalWeights ) ;
1456+ int flatIdx = _random . Next ( totalWeights ) ;
14331457 int i = flatIdx / _convWeights . Columns ;
14341458 int j = flatIdx % _convWeights . Columns ;
14351459
@@ -1531,6 +1555,7 @@ public static DistillingConv<T> Deserialize(BinaryReader reader)
15311555internal class InformerDecoderLayer < T >
15321556{
15331557 private readonly INumericOperations < T > _numOps ;
1558+ private readonly Random _random ;
15341559 private readonly int _embeddingDim ;
15351560 private readonly int _numHeads ;
15361561 private readonly int _headDim ;
@@ -1571,11 +1596,12 @@ internal class InformerDecoderLayer<T>
15711596 public InformerDecoderLayer ( int embeddingDim , int numHeads , int sparsityFactor , double dropoutRate , int seed = 42 )
15721597 {
15731598 _numOps = MathHelper . GetNumericOperations < T > ( ) ;
1599+ _random = RandomHelper . CreateSeededRandom ( seed ) ;
15741600 _embeddingDim = embeddingDim ;
15751601 _numHeads = numHeads ;
15761602 _headDim = embeddingDim / numHeads ;
15771603
1578- var random = new Random ( seed ) ;
1604+ var random = RandomHelper . CreateSeededRandom ( seed ) ;
15791605 double attnStddev = Math . Sqrt ( 2.0 / embeddingDim ) ;
15801606 double ffnStddev = Math . Sqrt ( 2.0 / ( embeddingDim * 4 ) ) ;
15811607
@@ -1610,6 +1636,7 @@ public InformerDecoderLayer(int embeddingDim, int numHeads, int sparsityFactor,
16101636 private InformerDecoderLayer ( )
16111637 {
16121638 _numOps = MathHelper . GetNumericOperations < T > ( ) ;
1639+ _random = RandomHelper . CreateSeededRandom ( 42 ) ;
16131640 _embeddingDim = 0 ;
16141641 _numHeads = 1 ;
16151642 _headDim = 0 ;
@@ -1862,7 +1889,7 @@ private T DotProduct(Vector<T> a, Vector<T> b)
18621889 public void UpdateWeights ( Vector < T > input , T target , T learningRate , T epsilon , T twoEpsilon ,
18631890 Func < Vector < T > , T > predict , int sampleSize )
18641891 {
1865- var random = new Random ( ) ;
1892+ // Use seeded Random for reproducibility
18661893 var allMatrices = new [ ] {
18671894 _selfQueryProj , _selfKeyProj , _selfValueProj , _selfOutputProj ,
18681895 _crossQueryProj , _crossKeyProj , _crossValueProj , _crossOutputProj ,
@@ -1876,7 +1903,7 @@ public void UpdateWeights(Vector<T> input, T target, T learningRate, T epsilon,
18761903
18771904 for ( int s = 0 ; s < actualSample ; s ++ )
18781905 {
1879- int flatIdx = random . Next ( totalWeights ) ;
1906+ int flatIdx = _random . Next ( totalWeights ) ;
18801907 int i = flatIdx / matrix . Columns ;
18811908 int j = flatIdx % matrix . Columns ;
18821909
0 commit comments