@@ -185,29 +185,26 @@ public override T PredictSingle(Vector<T> input)
185185 /// <returns>Boolean array where true indicates an anomaly.</returns>
186186 public bool [ ] DetectAnomalies ( Vector < T > data )
187187 {
188- if ( data . Length < _options . WindowSize )
189- throw new ArgumentException ( $ "Data length must be at least { _options . WindowSize } ") ;
188+ if ( data . Length <= _options . WindowSize )
189+ throw new ArgumentException ( $ "Data length must be greater than { _options . WindowSize } ") ;
190190
191- bool [ ] anomalies = new bool [ data . Length - _options . WindowSize + 1 ] ;
191+ // Each anomaly score corresponds to comparing prediction from window ending at i with actual value at i
192+ int numResults = data . Length - _options . WindowSize ;
193+ bool [ ] anomalies = new bool [ numResults ] ;
192194
193- for ( int i = 0 ; i <= data . Length - _options . WindowSize ; i ++ )
195+ for ( int i = 0 ; i < numResults ; i ++ )
194196 {
195- // Extract window
197+ // Extract window ending at position i + WindowSize - 1
196198 Vector < T > window = new Vector < T > ( _options . WindowSize ) ;
197199 for ( int j = 0 ; j < _options . WindowSize ; j ++ )
198200 window [ j ] = data [ i + j ] ;
199201
200- // Predict next value
202+ // Predict next value and compare with actual
201203 T prediction = PredictSingle ( window ) ;
204+ T actual = data [ i + _options . WindowSize ] ;
205+ T error = _numOps . Abs ( _numOps . Subtract ( actual , prediction ) ) ;
202206
203- // Compare with actual next value (if available)
204- if ( i + _options . WindowSize < data . Length )
205- {
206- T actual = data [ i + _options . WindowSize ] ;
207- T error = _numOps . Abs ( _numOps . Subtract ( actual , prediction ) ) ;
208-
209- anomalies [ i ] = _numOps . GreaterThan ( error , _anomalyThreshold ) ;
210- }
207+ anomalies [ i ] = _numOps . GreaterThan ( error , _anomalyThreshold ) ;
211208 }
212209
213210 return anomalies ;
@@ -218,25 +215,23 @@ public bool[] DetectAnomalies(Vector<T> data)
218215 /// </summary>
219216 public Vector < T > ComputeAnomalyScores ( Vector < T > data )
220217 {
221- if ( data . Length < _options . WindowSize )
222- throw new ArgumentException ( $ "Data length must be at least { _options . WindowSize } ") ;
218+ if ( data . Length <= _options . WindowSize )
219+ throw new ArgumentException ( $ "Data length must be greater than { _options . WindowSize } ") ;
223220
224- var scores = new Vector < T > ( data . Length - _options . WindowSize + 1 ) ;
221+ // Each score corresponds to comparing prediction from window ending at i with actual value at i
222+ int numResults = data . Length - _options . WindowSize ;
223+ var scores = new Vector < T > ( numResults ) ;
225224
226- for ( int i = 0 ; i <= data . Length - _options . WindowSize ; i ++ )
225+ for ( int i = 0 ; i < numResults ; i ++ )
227226 {
228227 Vector < T > window = new Vector < T > ( _options . WindowSize ) ;
229228 for ( int j = 0 ; j < _options . WindowSize ; j ++ )
230229 window [ j ] = data [ i + j ] ;
231230
232231 T prediction = PredictSingle ( window ) ;
233-
234- if ( i + _options . WindowSize < data . Length )
235- {
236- T actual = data [ i + _options . WindowSize ] ;
237- T error = _numOps . Abs ( _numOps . Subtract ( actual , prediction ) ) ;
238- scores [ i ] = error ;
239- }
232+ T actual = data [ i + _options . WindowSize ] ;
233+ T error = _numOps . Abs ( _numOps . Subtract ( actual , prediction ) ) ;
234+ scores [ i ] = error ;
240235 }
241236
242237 return scores ;
0 commit comments