اینجاست که تشخیص ناهنجاری (Anomaly Detection) به کمک یادگیری ماشین (Machine Learning) وارد عمل میشود. ناهنجاری به زبانی ساده، به دادههایی گفته میشود که با رفتار استاندارد و الگوی عمومی پیشین دادهها مطابقت ندارند.
به عنوان یک مهندس نرمافزار ارشد یا معمار سیستم در اکوسیستم داتنت، پیادهسازی چنین سیستمهایی در گذشته نیازمند خروج از چارچوب .NET و اتکا به سرویسها یا لایههای پایتون (با کتابخانههایی مثل Scikit-Learn) بود. این تغییر بستر (Context Switching) چالشهایی مانند تأخیر در فراخوانیهای شبکه، پیچیدگی دپلویمنت و عدم هماهنگی تایپها را به همراه داشت. اما امروز به لطف ML.NET (فریمورک متنباز و کرسپلتفرم مایکروسافت)، ما میتوانیم مدلهای پیشرفته یادگیری ماشین را به صورت بومی (Native)، با عملکرد فوقالعاده بالا و مستقیماً درون پروژههای داتنت (C#) خود پیادهسازی کنیم.
در این مقاله تخصصی، معماری، الگوریتمها و پیادهسازی عملی یک سیستم تشخیص ناهنجاری در دادههای مالی را با استفاده از .NET 8/9 و ML.NET به صورت گامبهگام بررسی خواهیم کرد.
پیش از کدنویسی، باید ماهیت دادههایی را که با آنها سروکار داریم بشناسیم. در دامنههای مالی، ناهنجاریها عموماً به سه دسته اصلی تقسیم میشوند:
ناهنجاریهای نقطهای (Point Anomalies): زمانی رخ میدهد که یک داده فردی نسبت به بقیه دادهها به شدت آسیبرسان یا عجیب باشد.
مثال مالی: تراکنش ناگهانی به ارزش ۵۰,۰۰۰ دلار از کارتی که میانگین خرید ماهانه آن ۵۰ دلار بوده است.
ناهنجاریهای زمینهای (Contextual Anomalies): در این حالت، داده به خودی خود ناهنجار نیست، اما قرارگیری آن در یک «زمینه یا بافت خاص» آن را به ناهنجاری تبدیل میکند. زمان و مکان در این بخش نقشی اساسی دارند.
مثال مالی: برداشت ۱۰۰ دلار از دستگاه خودپرداز در تهران، و سپس برداشت ۲۰۰ دلار دیگر تنها ۱۰ دقیقه بعد از دستگاهی در برلین. خریدها به خودی خود عادی هستند، اما زمینه زمانی/مکانی غیرممکن است.
ناهنجاریهای دستهای (Collective Anomalies): مجموعهای از دادهها که به صورت انفرادی عادی به نظر میرسند، اما تکرار و رفتار گروهی آنها نشاندهنده یک پدیده غیرعادی است.
مثال مالی: حملات سایبری از نوع کلاهبرداریهای خرد (Micro-transaction Fraud) که در آن مبالغ بسیار ناچیزی (مثلاً چند سنت) به صورت متوالی و با سرعت بالا از هزاران حساب برداشت میشود تا سیستمهای هشدار سنتی حساس نشوند.
برای دادههای مالی (که اغلب به صورت سری زمانی یا تراکنشی هستند)، کتابخانه ML.NET ابزارهای تخصصی بسیار قدرتمندی ارائه میدهد. انتخاب الگوریتم بستگی به سناریوی شما دارد:
۱. الگوریتم SrCnn (Spectral Residual - Convolutional Neural Network)
۲. الگوریتم IID (Independent and Identically Distributed) Spike/Change Point
۳. الگوریتم One-Class SVM یا Randomized Pca
نکته معماری: در این مقاله، تمرکز ما روی دادههای تراکنشیِ متوالی (سری زمانی) یک حساب بانکی با الگوریتم SrCnn است که یکی از پیشرفتهترین و پایدارترین روشها برای دادههای مالی با نوسانات فصلی (مثلاً افزایش خرید در آستانه سال نو) به شمار میرود.
برای پیادهسازی این پروژه روی ویندوز، مراحل زیر را طی کنید:
۱. نصب .NET SDK
مطمئن شوید که .NET 8 SDK یا نسخههای بالاتر (مانند .NET 9) روی ویندوز شما نصب است. ترمینال (PowerShell) را باز کنید و دستور زیر را برای بررسی نسخه بزنید:
dotnet --version
۲. ایجاد یک پروژه Console در سیشارپ
یک پروژه کنسول جدید ایجاد کرده و وارد پوشه آن شوید:
dotnet new console -n FinancialAnomalyDetector
cd FinancialAnomalyDetector
۳. نصب پکیجهای نیوگت (NuGet) مربوط به ML.NET
برای دسترسی به قابلیتهای اصلی یادگیری ماشین و پردازش سری زمانی، پکیجهای زیر را نصب کنید:
dotnet add package Microsoft.ML
dotnet add package Microsoft.ML.TimeSeries
فرض کنید میخواهیم جریان تراکنشهای روزانه یک حساب یا یک صادرکننده کارت را مانیتور کنیم تا اگر جهش یا افت عجیبی در حجم مالی رخ داد، سریعاً سیستم امنیتی را باخبر سازیم.
گام اول: تعریف ساختار دادهها (Data Models)
ابتدا مدلهای دادهای خود را برای ورودی (تراکنش) و خروجی (پیشبینی ناهنجاری) تعریف میکنیم. یک فایل به نام TransactionModel.cs ایجاد کنید:
using Microsoft.ML.Data;
namespace FinancialAnomalyDetector
{
// مدل داده ورودی تراکنش مالی
public class FinancialData
{
[LoadColumn(0)]
public string Date { get; set; }
[LoadColumn(1)]
public float Amount { get; set; }
}
// مدل خروجی پیشبینی سیستم تشخیص ناهنجاری
public class AnomalyPrediction
{
// خروجی الگوریتم به صورت یک آرایه ۳ مقداره است:
// [0] = آیا ناهنجاری است؟ (0 یا 1)
// [1] = مقدار خام امتیاز ناهنجاری (Raw Score)
// [2] = مقدار P-Value (هرچه به صفر نزدیکتر باشد، احتمال ناهنجاری بیشتر است)
[VectorType(3)]
public double[] Prediction { get; set; }
}
}
گام دوم: پیادهسازی خط لوله یادگیری (ML Pipeline) و منطق پردازش
در این گام، دیتای فرضی مالی را تولید کرده، لوله پردازش الگو را با متد SrCnn پیکربندی نموده و مدل را اجرا میکنیم. فایل Program.cs را باز کرده و کدهای زیر را جایگزین کنید:
using System;
using System.Collections.Generic;
using Microsoft.ML;
using FinancialAnomalyDetector;
class Program
{
static void Main(string[] args)
{
// ۱. مقداردهی اولیه به محیط متمرکز ML.NET
var mlContext = new MLContext(seed: 42);
// ۲. ایجاد دادههای شبهواقعی مالی (تراکنشهای روزانه)
// یک الگوی عادی حول و حوش ۱۰۰ تا ۱۵۰ دلار با چند ناهنجاری شدید (مثلا خرید ۵۰۰۰ دلاری)
var financialTransactions = GenerateSampleData();
// ۳. بارگذاری دادهها در ساختار بومی IDataView
var dataView = mlContext.Data.LoadFromEnumerable(financialTransactions);
// ۴. پیکربندی خط لوله تشخیص ناهنجاری با الگوریتم SrCnn
// پارامترهای مهم:
// - outputColumnName: نام ستون خروجی
// - inputColumnName: ستون ورودی که باید پایش شود (Amount)
// - threshold: آستانه حساسیت (بین 0 تا 1). مقادیر کمتر = حساسیت بیشتر به ناهنجاری
// - windowSize: اندازه پنجره متحرک برای بررسی الگوهای محلی داده
var anomalyDetectionPipeline = mlContext.Transforms.DetectAnomalyBySrCnn(
outputColumnName: nameof(AnomalyPrediction.Prediction),
inputColumnName: nameof(FinancialData.Amount),
threshold: 0.3,
windowSize: 16,
backpropagationWindowSize: 16,
anomalyMode: AnomalyMode.AnomalyOnly
);
// ۵. آموزش/برازش مدل روی دادهها
Console.WriteLine("--- در حال تحلیل لایه دادههای مالی و آموزش مدل ---");
var trainedModel = anomalyDetectionPipeline.Fit(dataView);
// ۶. تبدیل دادهها و استخراج خروجی پیشبینی
var transformedData = trainedModel.Transform(dataView);
var predictions = mlContext.Data.CreateEnumerable<AnomalyPrediction>(transformedData, reuseRowObject: false);
// ۷. نمایش نتایج تحلیل در خروجی کنسول
Console.WriteLine("\n--- نتایج سیستم هوشمند تشخیص ناهنجاری مالی ---");
Console.WriteLine("ردیف\tتاریخ\t\tمبلغ ($)\tوضعیت\t\tP-Value");
Console.WriteLine("=============================================================");
int index = 0;
using (var enumerator = financialTransactions.GetEnumerator())
{
foreach (var pred in predictions)
{
if (enumerator.MoveNext())
{
var originalData = enumerator.Current;
bool isAnomaly = pred.Prediction[0] == 1;
double pValue = pred.Prediction[2];
// تغییر رنگ کنسول در صورت ردیابی ناهنجاری مالی برای جلب توجه اپراتور
if (isAnomaly)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"{index}\t{originalData.Date}\t{originalData.Amount}\t\t[⚠️ ناهنجاری]\t{pValue:F4}");
Console.ResetColor();
}
else
{
Console.WriteLine($"{index}\t{originalData.Date}\t{originalData.Amount}\t\t[عادی]\t\t{pValue:F4}");
}
index++;
}
}
}
Console.ReadLine();
}
// متد کمکی برای تولید دیتای تست مالی
private static List<FinancialData> GenerateSampleData()
{
var data = new List<FinancialData>();
var baseDate = new DateTime(2026, 1, 1);
var random = new Random(50);
for (int i = 0; i < 60; i++)
{
// رفتار نرمال: نوسان تصادفی بین ۱۰۰ تا ۱۸۰ دلار
float amount = random.Next(100, 180);
// ایجاد عمدی ناهنجاریهای نقطهای و زمینهای شدید در روزهای خاص
if (i == 12) amount = 4500f; // هک یا خرید ناگهانی کلان (Positive Spike)
if (i == 35) amount = 5f; // افت ناگهانی و شدید حجم تراکنش (Negative Spike)
if (i == 48) amount = 3900f; // یک ناهنجاری مالی دیگر
data.Add(new FinancialData
{
Date = baseDate.AddDays(i).ToString("yyyy-MM-dd"),
Amount = amount
});
}
return data;
}
}
وقتی این پروژه را با کلید F5 یا دستور dotnet run در ویندوز اجرا میکنید، خروجی مشابه زیر دریافت خواهید کرد:
--- در حال تحلیل لایه دادههای مالی و آموزش مدل ---
--- نتایج سیستم هوشمند تشخیص ناهنجاری مالی ---
ردیف تاریخ مبلغ ($) وضعیت P-Value
=============================================================
0 2026-01-01 147 [عادی] 0.5000
...
11 2026-01-12 112 [عادی] 0.4821
12 2026-01-13 4500 [⚠️ ناهنجاری] 0.0000
13 2026-01-14 135 [عادی] 0.5112
...
34 2026-01-04 162 [عادی] 0.4902
35 2026-02-05 5 [⚠️ ناهنجاری] 0.0002
تحلیل مکانیزم دیتکشن
مقدار P-Value چیست؟ این مقدار نشاندهنده میزان اطمینان الگو به نرمال بودن داده است. هرچه رفتار داده به میانگین متحرک و فرکانسهای ثبتشده در windowSize شبیه باشد، این عدد به 0.5 الی 1.0 نزدیکتر است. اما در روزهای ۱۲ و ۳۵، این مقدار به شدت سقوط کرده و نزدیک به صفر (0.0000) میشود.
چرا این روش برتر از هاردکد کردن قوانین است؟ الگوریتم SrCnn به خوبی متوجه چیدمان دادهها میشود. اگر به مرور زمان میانگین تراکنشهای این حساب به علت تورم یا تغییر شغل کاربر از ۱۵۰ دلار به ۱۰۰۰ دلار برسد، مدل خود را با فرمت جدید تطبیق میدهد (Adaptability) و دیگر تراکنشهای ۱۰۰۰ دلاری را به عنوان هشدار کاذب (False Positive) علامتگذاری نمیکند، چیزی که در سیستمهای سنتی Rule-based عملاً ناممکن است.
به عنوان یک مهندس ارشد، برای بردن این کد به محیط عملیاتی بانک یا صرافی، باید نکات زیر را رعایت کنید:
مدیریت بهینه حافظه با PredictionEnginePool: در وبسرویسها (تایپ ASP.NET Core Web API) هرگز نباید برای هر درخواست کلاینت یک نمونه جدید از کلاس پیشبینی بسازید زیرا Thread-safe نیست. به جای آن از Dependency Injection و پکیج Microsoft.Extensions.ML استفاده کنید تا مدیریت ریسورسها به صورت استخر (Pool) انجام شود:
builder.Services.AddPredictionEnginePool<FinancialData, AnomalyPrediction>()
.FromFile("ModelFilePath.zip");
2. **ذخیرهسازی و بازآموزی (Retraining) مدل:**
شما میتوانید مدل آموزشدیده را به صورت یک فایل با پسوند `.zip` ذخیره کنید تا نیازی نباشد با هر بار بالا آمدن سرور، مدل دوباره آموزش ببیند:
```csharp
mlContext.Model.Save(trainedModel, dataView.Schema, "financial_model.zip");
سپس یک جاب زمانبندی شده (Cron Job) تنظیم کنید تا هر هفته دیتای جدید تراکنشها را برداشته و مدل را بازآموزی کند.
کنترل هشدارهای کاذب (False Positives): در حوزه مالی، حساسیت بیش از حد سیستم مساوی است با مسدود شدن کارتهای کاربران عادی و نارضایتی شدید. پارامتر threshold را با کمک دیتای واقعیِ گذشته (Historical Data) آنقدر بهینهسازی کنید تا نرخ دقت سیستم (Precision/Recall) به تعادل برسد.
با استفاده از .NET و فریمورک قدرتمند ML.NET ثابت کردیم که پیادهسازی هوش مصنوعی و مدلهای یادگیری ماشین در کلاس جهانی، دیگر انحصاراً در دست زبانهای دیگر نیست. ما توانستیم بدون خروج از اکوسیستم امن و پرسرعت سیشارپ، یک سیستم کارآمد برای شناسایی ناهنجاریهای مالی بسازیم. این رویکرد یکپارچه، خطاهای معماری را کاهش داده، سرعت اجرا را بهینهتر کرده و دپلویمنت روی سرورهای ویندوزی یا لینوکسی (در قالب کانتینرهای Docker) را به شدت تسهیل میکند.
1 نظر