首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

測試運行:將數值數據轉換為分類數據(離散化演算法實作)

     編輯:關於.NET

前言:為什麼需要數據離散化

機器學習中常需將連續數值(如身高 59.5、64.0、75.5 英吋)轉換為類別標籤(矮/中/高 → 0/1/2),此過程稱為「數據裝箱」或「連續數據離散化」。許多演算法(如 Naive Bayes)僅接受類別特徵;混合數值與類別特徵時,將數值離散化可統一套用分類演算法(如分類效用進行分群)。

簡單方法的缺失

  • 等寬區間:將範圍均分,忽略資料自然分佈間隙。
  • 等頻區間:每類樣本數相同,同樣忽略自然間隙。

本文採用 K-means 分群 進行離散化:先對數據分群,取各群質心(平均值)作為代表;新數值根據最近質心歸類,自然貼合資料分佈。

演示程式架構

double[] rawData = { 66,66,66,67,67,67,67,68,68,69,73,73,73,74,76,78,60,61,62,62 };
Discretizer d = new Discretizer(rawData);
int cat = d.Discretize(75.5); // → 2

核心類別 Discretizer 四大欄位:

  • data:去重後排序的原始數值陣列
  • k:類別數(啟發式取 sqrt(data.Length))
  • means:各群質心(平均值)
  • clustering:各資料點所屬群索引

Discretizer 建構子與去重

public Discretizer(double[] rawData) {
    double[] sorted = new double[rawData.Length];
    Array.Copy(rawData, sorted, rawData.Length);
    Array.Sort(sorted);
    this.data = GetDistinctValues(sorted);
    this.clustering = new int[data.Length];
    this.k = (int)Math.Sqrt(data.Length);
    this.means = new double[k];
    Cluster();
}
private static double[] GetDistinctValues(double[] sorted) {
    var list = new List<double> { sorted[0] };
    for (int i = 0; i < sorted.Length - 1; i++)
        if (!AreEqual(sorted[i], sorted[i+1])) list.Add(sorted[i+1]);
    return list.ToArray();
}
private static bool AreEqual(double x1, double x2) => Math.Abs(x1 - x2) < 1e-6;

K-means 分群流程

  1. 初始化:等頻分配初始群索引(InitializeClustering)。
  2. 計算質心:ComputeMeans 依群索引累加平均,若某群無成員回傳 false。
  3. 重新指派:AssignAll 計算每點到各質心的歐氏距離(單維即絕對差),指派最近群。
  4. 迴圈直到分群不再變動、質心計算失敗或達最大迭代次數(data.Length * 10)。
private void Cluster() {
    InitializeClustering(); ComputeMeans();
    bool changed = true, success = true; int ct = 0, maxCt = data.Length * 10;
    while (changed && success && ct < maxCt) {
        ct++; changed = AssignAll(); success = ComputeMeans();
    }
}
private bool AssignAll() {
    bool changed = false;
    for (int i = 0; i < data.Length; i++) {
        double[] dists = new double[k];
        for (int c = 0; c < k; c++) dists[c] = Distance(data[i], means[c]);
        int newCluster = MinIndex(dists);
        if (newCluster != clustering[i]) { clustering[i] = newCluster; changed = true; }
    }
    return changed;
}
private static double Distance(double x1, double x2) => Math.Abs(x1 - x2); // 單維歐氏距離

離散化新數值

分群完成後,means 保存各群質心。Discretize(x) 計算 x 到各質心距離,回傳最近質心索引:

public int Discretize(double x) {
    double[] dists = new double[k];
    for (int c = 0; c < k; c++) dists[c] = Distance(x, means[c]);
    return MinIndex(dists);
}

示範結果:原始 11 個去重值分為 3 群,質心約 61.0、67.5、75.25。測試值 62.0→0、66.0→1、73.0→2、59.5→0、75.5→2、80.5→2。

總結與擴充建議

  • 程式碼可直接整合至類別庫使用。
  • 關鍵可調參數:類別數 k(預設 sqrt(N))、浮點比較閾值 epsilon、最大迭代次數。
  • 若定義域明確(如年齡 1~120),可直接設 k=120 而非啟發式值。

完整原始碼下載:archive.msdn.microsoft.com/mag201308TestRun

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved