2017 年 4 月

# 测试运行 - 使用 C# 的内核感知器

21 定型数据点具有循环的几何，这就意味着简单的线性分类技术，如普通感知或逻辑回归中，较为低效。此类数据称为非线性可分离。

## 了解的内核函数

``````K(x1, x2) = exp( - || x1 - x2 ||^2 / (2 * sigma^2) )
``````

RBF，更好地示例进行说明。假设 x1 = （2.0、 1.0 和 3.0） 和 x2 = （0.0，1.0，5.0），和 sigma 为 1.0。首先，您可以计算的平方的欧几里得距离︰

``````|| x1 - x2 ||^2 = (2.0 - 0.0)^2 + (1.0 - 1.0)^2  + (3.0 - 5.0)^2
= 4.0 + 0.0 + 4.0
= 8.0
``````

``````8.0 / (2 * (1.0)^2) = 8.0 / 2.0 = 4.0
``````

``````K = e^(-4.0) = 0.0183
``````

``````static double Kernel(double[] d1, double[] d2, double sigma) {
double num = 0.0;
for (int i = 0; i < d1.Length - 1; ++i)
num += (d1[i] - d2[i]) * (d1[i] - d2[i]);
double denom = 2.0 * sigma * sigma;
double z = num / denom;
double result = Math.Exp(-z);
return result;
}
``````

## 了解普通感知

``````sum = (w0)(x0) + (w1)(x1) +(w2)(x2) + b
= (1.5)(4.0) + (1.1)(3.0) + (-3.0)(5.0) + 2.5
= 6.0 + 3.3 + (-15.0) + 2.5
= -3.2
prediction = sign(sum)
= -1
``````

``````sum = (2.5)(1.0) + (1.5)(4.0) + (1.1)(3.0) + (-3.0)(5.0)
= -3.2
``````

## 内核感知器算法

``````K(td[0], x) = 0.1083
K(td[1], x) = 0.0285
K(td[2], x) = 0.8007
K(td[3], x) = 0.1083
sum = (1)(0.1083)(-1) + (2)(0.0285)(+1) + (3)(0.8007)(+1) + (4)(0.1083)(-1)
= +1.9175
prediction = sign(sum)
= +1
``````

``````loop a few times
for each curr training item, i
for each other training item, j
sum += a[j] * K(td[i], td[j], sigma) * y[j];
end-for
pred = sign(sum)
if (pred is wrong) increment a[i]
end-for
end-loop
``````

## 演示程序结构

``````using System;
namespace KernelPerceptron
{
class KernelPerceptronProgram
{
static void Main(string[] args)
{
Console.WriteLine("Begin demo ");
int numFeatures = 2;
Console.WriteLine("Goal is classification(-1/+1) ");
Console.WriteLine("Setting up 21 training items ");
double[][] trainData = new double[21][];
trainData[0] = new double[] { 2.0, 3.0, -1 };
trainData[1] = new double[] { 2.0, 5.0, -1 };
. . .
trainData[20] = new double[] { 5.0, 6.0, +1 };
int numTrain = trainData.Length;
double[][] testData = new double[4][];
testData[0] = new double[] { 2.0, 4.0, -1 };
. .
testData[3] = new double[] { 5.5, 5.5, +1 };
int[] a = new int[trainData.Length];
int maxEpoch = 10;
int epoch = 0;
double sigma = 1.5;  // for the kernel function
Console.WriteLine("Starting train, sigma = 1.5 ");
...
Console.WriteLine("Training complete ");
double trainAcc = Accuracy(trainData, a,
trainData, sigma, false);  // silent
Console.WriteLine("Accuracy = " +
trainAcc.ToString("F4"));
Console.WriteLine("Analyzing test data: ");
double testAcc = Accuracy(testData, a,
trainData, sigma, true);  // verbose
Console.WriteLine("End kernel perceptron demo ");
} // Main
static double Kernel(double[] d1, double[] d2,
double sigma) { . . }
static double Accuracy(double[][] data, int[] a,
double[][] trainData, double sigma, bool verbose)
{ . . }
} // Program
} // ns
``````

``````int numFeatures = 2;
double[][] trainData = new double[21][];
trainData[0] = new double[] { 2.0, 3.0, -1 };
. .
trainData[20] = new double[] { 5.0, 6.0, +1 };
int numTrain = trainData.Length;
double[][] testData = new double[4][];
testData[0] = new double[] { 2.0, 4.0, -1 };
. .
testData[3] = new double[] { 5.5, 5.5, +1 };
``````

``````int[] a = new int[numTrain];  // "Wrong counters"
double sigma = 1.5;  // For the kernel function
int maxEpoch = 10;
int epoch = 0;
``````

``````double[][] kernelMatrix = new double[numTrain][];
for (int i = 0; i < kernelMatrix.Length; ++i)
kernelMatrix[i] = new double[numTrain];
for (int i = 0; i < numTrain; ++i) {
for (int j = 0; j < numTrain; ++j) {
double k = Kernel(trainData[i], trainData[j], sigma);
kernelMatrix[i][j] = kernelMatrix[j][i] = k;
}
}
``````

``````while (epoch < maxEpoch) {
for (int i = 0; i < numTrain; ++i) {
// Get "desired" correct class into di
for (int j = 0; j < numTrain; ++j) {
// Get "other" desired class into dj
// Compute y = weighted sum of products
}
if ((di == -1 && y >= 0.0) || (di == 1 && y <= 0.0))
++a[i]; // increment wrong counter
}
++epoch;
}
``````

（-1 或 + 1） 的所需，正确类来自当前的训练项替换为以下代码︰

``````int di = (int)trainData[i][numFeatures];
``````

``````double y = 0.0; // Weighted sum of kernel results
for (int j = 0; j < numTrain;; ++j) {
int dj = (int)trainData[j][numFeatures];
double kern = kernelMatrix[i][j];
y += a[j] * dj * kern;
}
``````

``````if ((di == -1 && y >= 0.0) || (di == 1 && y <= 0.0))
++a[i]; // wrong counter for curr data
``````

## 进行预测

Helper 函数准确性进行预测。该方法的定义开头︰

``````static double Accuracy(double[][] data, int[] a,
double[][] trainData, double sigma, bool verbose)
{
int numFeatures = data[0].Length - 1;
double[] x = new double[numFeatures];
int numCorrect = 0;
int numWrong = 0;
...
``````

``````if ((di == -1 && y >= 0.0) || (di == 1 && y <= 0.0))
++numWrong;
else
++numCorrect;
``````

``````return (1.0 * numCorrect) / (numCorrect + numWrong);
``````

``````if (verbose == true)
{
Console.Write("Input: ");
for (int j = 0; j < data[i].Length - 1; ++j)
Console.Write(data[i][j].ToString("F1") + " ");
// Etc.
}
``````

## 总结

Dr.James McCaffrey 供职于华盛顿地区雷蒙德市沃什湾的 Microsoft Research。他参与过多个 Microsoft 产品的工作，包括 Internet Explorer 和 Bing。Scripto可通过 jammc@microsoft.com 与 McCaffrey 取得联系。