機器學習中常需將連續數值(如身高 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:各資料點所屬群索引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;
InitializeClustering)。ComputeMeans 依群索引累加平均,若某群無成員回傳 false。AssignAll 計算每點到各質心的歐氏距離(單維即絕對差),指派最近群。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、最大迭代次數。k=120 而非啟發式值。