From 14c0a45e6f2ff4c634eee63444a5230d25301139 Mon Sep 17 00:00:00 2001 From: Bo Peng Date: Thu, 28 Mar 2019 15:44:07 -0500 Subject: [PATCH] implementing NB classifier --- TensorFlow.NET.sln | 6 + src/TensorFlowNET.Core/APIs/tf.math.cs | 3 + .../Distributions/distribution.py.cs | 5 +- .../Operations/Distributions/normal.py.cs | 19 ++- .../TensorFlowNET.Core.csproj | 4 + .../NaiveBayesClassifier.cs | 154 +++++++++--------- .../TensorFlowNET.Examples.csproj | 1 + 7 files changed, 110 insertions(+), 82 deletions(-) diff --git a/TensorFlow.NET.sln b/TensorFlow.NET.sln index e50bb267..cc879a0d 100644 --- a/TensorFlow.NET.sln +++ b/TensorFlow.NET.sln @@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.Core", "src\T EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TensorFlowNET.Visualization", "src\TensorFlowNET.Visualization\TensorFlowNET.Visualization.csproj", "{0254BFF9-453C-4FE0-9609-3644559A79CE}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NumSharp.Core", "..\NumSharp\src\NumSharp.Core\NumSharp.Core.csproj", "{A4428462-1147-45E9-8403-4E6860FF6EED}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +35,10 @@ Global {0254BFF9-453C-4FE0-9609-3644559A79CE}.Debug|Any CPU.Build.0 = Debug|Any CPU {0254BFF9-453C-4FE0-9609-3644559A79CE}.Release|Any CPU.ActiveCfg = Release|Any CPU {0254BFF9-453C-4FE0-9609-3644559A79CE}.Release|Any CPU.Build.0 = Release|Any CPU + {A4428462-1147-45E9-8403-4E6860FF6EED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4428462-1147-45E9-8403-4E6860FF6EED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4428462-1147-45E9-8403-4E6860FF6EED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4428462-1147-45E9-8403-4E6860FF6EED}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/TensorFlowNET.Core/APIs/tf.math.cs b/src/TensorFlowNET.Core/APIs/tf.math.cs index 24f09056..6ba7805a 100644 --- a/src/TensorFlowNET.Core/APIs/tf.math.cs +++ b/src/TensorFlowNET.Core/APIs/tf.math.cs @@ -152,6 +152,9 @@ namespace Tensorflow public static Tensor sub(Tensor a, Tensor b) => gen_math_ops.sub(a, b); + public static Tensor divide(Tensor a, Tensor b) + => gen_math_ops.real_div(a, b); + public static Tensor sqrt(Tensor a, string name = null) => gen_math_ops.sqrt(a, name); diff --git a/src/TensorFlowNET.Core/Operations/Distributions/distribution.py.cs b/src/TensorFlowNET.Core/Operations/Distributions/distribution.py.cs index 74f1fe3e..029b35bf 100644 --- a/src/TensorFlowNET.Core/Operations/Distributions/distribution.py.cs +++ b/src/TensorFlowNET.Core/Operations/Distributions/distribution.py.cs @@ -43,7 +43,7 @@ namespace Tensorflow private Tensor _call_log_prob (Tensor value, string name) { - with(ops.name_scope(name, "moments", new { value }), scope => + return with(ops.name_scope(name, "moments", new { value }), scope => { try { @@ -60,10 +60,9 @@ namespace Tensorflow } } }); - return null; } - private Tensor _log_prob(Tensor value) + protected virtual Tensor _log_prob(Tensor value) { throw new NotImplementedException(); } diff --git a/src/TensorFlowNET.Core/Operations/Distributions/normal.py.cs b/src/TensorFlowNET.Core/Operations/Distributions/normal.py.cs index e82b2ddd..e5243c17 100644 --- a/src/TensorFlowNET.Core/Operations/Distributions/normal.py.cs +++ b/src/TensorFlowNET.Core/Operations/Distributions/normal.py.cs @@ -79,25 +79,32 @@ namespace Tensorflow return array_ops.broadcast_static_shape(new Tensor(_loc.shape), new Tensor(_scale.shape)); } - private Tensor _log_prob(Tensor x) + protected override Tensor _log_prob(Tensor x) { - return _log_unnormalized_prob(_z(x)) -_log_normalization(); + var log_prob = _log_unnormalized_prob(_z(x)); + var log_norm = _log_normalization(); + return log_prob - log_norm; } private Tensor _log_unnormalized_prob (Tensor x) { return -0.5 * math_ops.square(_z(x)); } - + /// + /// Standardize input `x` to a unit normal. + /// + /// + /// private Tensor _z (Tensor x) { - return (x - this._loc) / this._scale; + return tf.divide(tf.sub(x, this._loc), this._scale); } private Tensor _log_normalization() { - Tensor t = new Tensor(Math.Log(2.0 * Math.PI)); - return 0.5 * t + math_ops.log(scale()); + Tensor t1 = ops.convert_to_tensor(Math.Log(2.0 * Math.PI), TF_DataType.TF_FLOAT); + Tensor t2 = tf.multiply(ops.convert_to_tensor(0.5, TF_DataType.TF_FLOAT), t1); + return tf.add(t2, math_ops.log(this._scale)); } } } \ No newline at end of file diff --git a/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj b/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj index a4188e15..58022230 100644 --- a/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj +++ b/src/TensorFlowNET.Core/TensorFlowNET.Core.csproj @@ -58,4 +58,8 @@ Bug memory leak issue when allocating Tensor. + + + + diff --git a/test/TensorFlowNET.Examples/NaiveBayesClassifier.cs b/test/TensorFlowNET.Examples/NaiveBayesClassifier.cs index d0a841e4..b9c4fe76 100644 --- a/test/TensorFlowNET.Examples/NaiveBayesClassifier.cs +++ b/test/TensorFlowNET.Examples/NaiveBayesClassifier.cs @@ -19,56 +19,56 @@ namespace TensorFlowNET.Examples public Normal dist { get; set; } public bool Run() { - var X = np.array(new double[][] { new double[] { 5.1, 3.5},new double[] { 4.9, 3.0 },new double[] { 4.7, 3.2 }, - new double[] { 4.6, 3.1 },new double[] { 5.0, 3.6 },new double[] { 5.4, 3.9 }, - new double[] { 4.6, 3.4 },new double[] { 5.0, 3.4 },new double[] { 4.4, 2.9 }, - new double[] { 4.9, 3.1 },new double[] { 5.4, 3.7 },new double[] {4.8, 3.4 }, - new double[] {4.8, 3.0 },new double[] {4.3, 3.0 },new double[] {5.8, 4.0 }, - new double[] {5.7, 4.4 },new double[] {5.4, 3.9 },new double[] {5.1, 3.5 }, - new double[] {5.7, 3.8 },new double[] {5.1, 3.8 },new double[] {5.4, 3.4 }, - new double[] {5.1, 3.7 },new double[] {5.1, 3.3 },new double[] {4.8, 3.4 }, - new double[] {5.0 , 3.0 },new double[] {5.0 , 3.4 },new double[] {5.2, 3.5 }, - new double[] {5.2, 3.4 },new double[] {4.7, 3.2 },new double[] {4.8, 3.1 }, - new double[] {5.4, 3.4 },new double[] {5.2, 4.1},new double[] {5.5, 4.2 }, - new double[] {4.9, 3.1 },new double[] {5.0 , 3.2 },new double[] {5.5, 3.5 }, - new double[] {4.9, 3.6 },new double[] {4.4, 3.0 },new double[] {5.1, 3.4 }, - new double[] {5.0 , 3.5 },new double[] {4.5, 2.3 },new double[] {4.4, 3.2 }, - new double[] {5.0 , 3.5 },new double[] {5.1, 3.8 },new double[] {4.8, 3.0}, - new double[] {5.1, 3.8 },new double[] {4.6, 3.2 },new double[] { 5.3, 3.7 }, - new double[] {5.0 , 3.3 },new double[] {7.0 , 3.2 },new double[] {6.4, 3.2 }, - new double[] {6.9, 3.1 },new double[] {5.5, 2.3 },new double[] {6.5, 2.8 }, - new double[] {5.7, 2.8 },new double[] {6.3, 3.3 },new double[] {4.9, 2.4 }, - new double[] {6.6, 2.9 },new double[] {5.2, 2.7 },new double[] {5.0 , 2.0 }, - new double[] {5.9, 3.0 },new double[] {6.0 , 2.2 },new double[] {6.1, 2.9 }, - new double[] {5.6, 2.9 },new double[] {6.7, 3.1 },new double[] {5.6, 3.0 }, - new double[] {5.8, 2.7 },new double[] {6.2, 2.2 },new double[] {5.6, 2.5 }, - new double[] {5.9, 3.0},new double[] {6.1, 2.8},new double[] {6.3, 2.5}, - new double[] {6.1, 2.8},new double[] {6.4, 2.9},new double[] {6.6, 3.0 }, - new double[] {6.8, 2.8},new double[] {6.7, 3.0 },new double[] {6.0 , 2.9}, - new double[] {5.7, 2.6},new double[] {5.5, 2.4},new double[] {5.5, 2.4}, - new double[] {5.8, 2.7},new double[] {6.0 , 2.7},new double[] {5.4, 3.0 }, - new double[] {6.0 , 3.4},new double[] {6.7, 3.1},new double[] {6.3, 2.3}, - new double[] {5.6, 3.0 },new double[] {5.5, 2.5},new double[] {5.5, 2.6}, - new double[] {6.1, 3.0 },new double[] {5.8, 2.6},new double[] {5.0 , 2.3}, - new double[] {5.6, 2.7},new double[] {5.7, 3.0 },new double[] {5.7, 2.9}, - new double[] {6.2, 2.9},new double[] {5.1, 2.5},new double[] {5.7, 2.8}, - new double[] {6.3, 3.3},new double[] {5.8, 2.7},new double[] {7.1, 3.0 }, - new double[] {6.3, 2.9},new double[] {6.5, 3.0 },new double[] {7.6, 3.0 }, - new double[] {4.9, 2.5},new double[] {7.3, 2.9},new double[] {6.7, 2.5}, - new double[] {7.2, 3.6},new double[] {6.5, 3.2},new double[] {6.4, 2.7}, - new double[] {6.8, 3.00 },new double[] {5.7, 2.5},new double[] {5.8, 2.8}, - new double[] {6.4, 3.2},new double[] {6.5, 3.0 },new double[] {7.7, 3.8}, - new double[] {7.7, 2.6},new double[] {6.0 , 2.2},new double[] {6.9, 3.2}, - new double[] {5.6, 2.8},new double[] {7.7, 2.8},new double[] {6.3, 2.7}, - new double[] {6.7, 3.3},new double[] {7.2, 3.2},new double[] {6.2, 2.8}, - new double[] {6.1, 3.0 },new double[] {6.4, 2.8},new double[] {7.2, 3.0 }, - new double[] {7.4, 2.8},new double[] {7.9, 3.8},new double[] {6.4, 2.8}, - new double[] {6.3, 2.8},new double[] {6.1, 2.6},new double[] {7.7, 3.0 }, - new double[] {6.3, 3.4},new double[] {6.4, 3.1},new double[] {6.0, 3.0}, - new double[] {6.9, 3.1},new double[] {6.7, 3.1},new double[] {6.9, 3.1}, - new double[] {5.8, 2.7},new double[] {6.8, 3.2},new double[] {6.7, 3.3}, - new double[] {6.7, 3.0 },new double[] {6.3, 2.5},new double[] {6.5, 3.0 }, - new double[] {6.2, 3.4},new double[] {5.9, 3.0 }, new double[] {5.8, 3.0 }}); + var X = np.array(new float[][] { new float[] { 5.1f, 3.5f},new float[] { 4.9f, 3.0f },new float[] { 4.7f, 3.2f }, + new float[] { 4.6f, 3.1f },new float[] { 5.0f, 3.6f },new float[] { 5.4f, 3.9f }, + new float[] { 4.6f, 3.4f },new float[] { 5.0f, 3.4f },new float[] { 4.4f, 2.9f }, + new float[] { 4.9f, 3.1f },new float[] { 5.4f, 3.7f },new float[] {4.8f, 3.4f }, + new float[] {4.8f, 3.0f },new float[] {4.3f, 3.0f },new float[] {5.8f, 4.0f }, + new float[] {5.7f, 4.4f },new float[] {5.4f, 3.9f },new float[] {5.1f, 3.5f }, + new float[] {5.7f, 3.8f },new float[] {5.1f, 3.8f },new float[] {5.4f, 3.4f }, + new float[] {5.1f, 3.7f },new float[] {5.1f, 3.3f },new float[] {4.8f, 3.4f }, + new float[] {5.0f, 3.0f },new float[] {5.0f , 3.4f },new float[] {5.2f, 3.5f }, + new float[] {5.2f, 3.4f },new float[] {4.7f, 3.2f },new float[] {4.8f, 3.1f }, + new float[] {5.4f, 3.4f },new float[] {5.2f, 4.1f},new float[] {5.5f, 4.2f }, + new float[] {4.9f, 3.1f },new float[] {5.0f , 3.2f },new float[] {5.5f, 3.5f }, + new float[] {4.9f, 3.6f },new float[] {4.4f, 3.0f },new float[] {5.1f, 3.4f }, + new float[] {5.0f , 3.5f },new float[] {4.5f, 2.3f },new float[] {4.4f, 3.2f }, + new float[] {5.0f , 3.5f },new float[] {5.1f, 3.8f },new float[] {4.8f, 3.0f}, + new float[] {5.1f, 3.8f },new float[] {4.6f, 3.2f },new float[] { 5.3f, 3.7f }, + new float[] {5.0f , 3.3f },new float[] {7.0f , 3.2f },new float[] {6.4f, 3.2f }, + new float[] {6.9f, 3.1f },new float[] {5.5f, 2.3f },new float[] {6.5f, 2.8f }, + new float[] {5.7f, 2.8f },new float[] {6.3f, 3.3f },new float[] {4.9f, 2.4f }, + new float[] {6.6f, 2.9f },new float[] {5.2f, 2.7f },new float[] {5.0f , 2.0f }, + new float[] {5.9f, 3.0f },new float[] {6.0f , 2.2f },new float[] {6.1f, 2.9f }, + new float[] {5.6f, 2.9f },new float[] {6.7f, 3.1f },new float[] {5.6f, 3.0f }, + new float[] {5.8f, 2.7f },new float[] {6.2f, 2.2f },new float[] {5.6f, 2.5f }, + new float[] {5.9f, 3.0f},new float[] {6.1f, 2.8f},new float[] {6.3f, 2.5f}, + new float[] {6.1f, 2.8f},new float[] {6.4f, 2.9f},new float[] {6.6f, 3.0f }, + new float[] {6.8f, 2.8f},new float[] {6.7f, 3.0f },new float[] {6.0f , 2.9f}, + new float[] {5.7f, 2.6f},new float[] {5.5f, 2.4f},new float[] {5.5f, 2.4f}, + new float[] {5.8f, 2.7f},new float[] {6.0f , 2.7f},new float[] {5.4f, 3.0f}, + new float[] {6.0f , 3.4f},new float[] {6.7f, 3.1f},new float[] {6.3f, 2.3f}, + new float[] {5.6f, 3.0f },new float[] {5.5f, 2.5f},new float[] {5.5f, 2.6f}, + new float[] {6.1f, 3.0f },new float[] {5.8f, 2.6f},new float[] {5.0f, 2.3f}, + new float[] {5.6f, 2.7f},new float[] {5.7f, 3.0f },new float[] {5.7f, 2.9f}, + new float[] {6.2f, 2.9f},new float[] {5.1f, 2.5f},new float[] {5.7f, 2.8f}, + new float[] {6.3f, 3.3f},new float[] {5.8f, 2.7f},new float[] {7.1f, 3.0f }, + new float[] {6.3f, 2.9f},new float[] {6.5f, 3.0f },new float[] {7.6f, 3.0f }, + new float[] {4.9f, 2.5f},new float[] {7.3f, 2.9f},new float[] {6.7f, 2.5f}, + new float[] {7.2f, 3.6f},new float[] {6.5f, 3.2f},new float[] {6.4f, 2.7f}, + new float[] {6.8f, 3.00f },new float[] {5.7f, 2.5f},new float[] {5.8f, 2.8f}, + new float[] {6.4f, 3.2f},new float[] {6.5f, 3.0f },new float[] {7.7f, 3.8f}, + new float[] {7.7f, 2.6f},new float[] {6.0f , 2.2f},new float[] {6.9f, 3.2f}, + new float[] {5.6f, 2.8f},new float[] {7.7f, 2.8f},new float[] {6.3f, 2.7f}, + new float[] {6.7f, 3.3f},new float[] {7.2f, 3.2f},new float[] {6.2f, 2.8f}, + new float[] {6.1f, 3.0f },new float[] {6.4f, 2.8f},new float[] {7.2f, 3.0f }, + new float[] {7.4f, 2.8f},new float[] {7.9f, 3.8f},new float[] {6.4f, 2.8f}, + new float[] {6.3f, 2.8f},new float[] {6.1f, 2.6f},new float[] {7.7f, 3.0f }, + new float[] {6.3f, 3.4f},new float[] {6.4f, 3.1f},new float[] {6.0f, 3.0f}, + new float[] {6.9f, 3.1f},new float[] {6.7f, 3.1f},new float[] {6.9f, 3.1f}, + new float[] {5.8f, 2.7f},new float[] {6.8f, 3.2f},new float[] {6.7f, 3.3f}, + new float[] {6.7f, 3.0f },new float[] {6.3f, 2.5f},new float[] {6.5f, 3.0f }, + new float[] {6.2f, 3.4f},new float[] {5.9f, 3.0f }, new float[] {5.8f, 3.0f }}); var y = np.array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -79,15 +79,18 @@ namespace TensorFlowNET.Examples 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); fit(X, y); // Create a regular grid and classify each point - double x_min = (double) X.amin(0)[0] - 0.5; - double y_min = (double) X.amin(0)[1] - 0.5; - double x_max = (double) X.amax(0)[0] + 0.5; - double y_max = (double) X.amax(0)[1] + 0.5; + float x_min = X.amin(0).Data(0) - 0.5f; + float y_min = X.amin(0).Data(1) - 0.5f; + float x_max = X.amax(0).Data(0) + 0.5f; + float y_max = X.amax(0).Data(1) + 0.5f; var (xx, yy) = np.meshgrid(np.linspace(x_min, x_max, 30), np.linspace(y_min, y_max, 30)); var s = tf.Session(); - var samples = np.vstack(xx.ravel(), yy.ravel()); - var Z = s.run(predict(samples)); + if (xx.dtype == typeof(float)) + { + var samples = np.vstack (xx.ravel(), yy.ravel()); + var Z = s.run(predict(samples)); + } return true; @@ -97,11 +100,11 @@ namespace TensorFlowNET.Examples { NDArray unique_y = y.unique(); - Dictionary>> dic = new Dictionary>>(); + Dictionary>> dic = new Dictionary>>(); // Init uy in dic foreach (int uy in unique_y.Data()) { - dic.Add(uy, new List>()); + dic.Add(uy, new List>()); } // Separate training points by class // Shape : nb_classes * nb_samples * nb_features @@ -109,10 +112,10 @@ namespace TensorFlowNET.Examples for (int i = 0; i < y.size; i++) { long curClass = (long)y[i]; - List> l = dic[curClass]; - List pair = new List(); - pair.Add((double)X[i,0]); - pair.Add((double)X[i, 1]); + List> l = dic[curClass]; + List pair = new List(); + pair.Add((float)X[i,0]); + pair.Add((float)X[i, 1]); l.Add(pair); if (l.Count > maxCount) { @@ -120,8 +123,8 @@ namespace TensorFlowNET.Examples } dic[curClass] = l; } - double[,,] points = new double[dic.Count, maxCount, X.shape[1]]; - foreach (KeyValuePair>> kv in dic) + float[,,] points = new float[dic.Count, maxCount, X.shape[1]]; + foreach (KeyValuePair>> kv in dic) { int j = (int) kv.Key; for (int i = 0; i < maxCount; i++) @@ -133,7 +136,7 @@ namespace TensorFlowNET.Examples } } - NDArray points_by_class = np.array(points); + NDArray points_by_class = np.array(points); // estimate mean and variance for each class / feature // shape : nb_classes * nb_features var cons = tf.constant(points_by_class); @@ -158,17 +161,22 @@ namespace TensorFlowNET.Examples // Conditional probabilities log P(x|c) with shape // (nb_samples, nb_classes) - var t1= ops.convert_to_tensor(X, TF_DataType.TF_DOUBLE); - //var t2 = ops.convert_to_tensor(new int[] { 1, nb_classes }); - //Tensor tile = tf.tile(t1, t2); - Tensor tile = tf.tile(X, new int[] { 1, nb_classes }); - Tensor r = tf.reshape(tile, new Tensor(new int[] { -1, nb_classes, nb_features })); - var cond_probs = tf.reduce_sum(dist.log_prob(r)); + var t1= ops.convert_to_tensor(X, TF_DataType.TF_FLOAT); + var t2 = ops.convert_to_tensor(new int[] { 1, nb_classes }); + Tensor tile = tf.tile(t1, t2); + var t3 = ops.convert_to_tensor(new int[] { -1, nb_classes, nb_features }); + Tensor r = tf.reshape(tile, t3); + var cond_probs = tf.reduce_sum(dist.log_prob(r), 2); // uniform priors - var priors = np.log(np.array((1.0 / nb_classes) * nb_classes)); + float[] tem = new float[nb_classes]; + for (int i = 0; i < tem.Length; i++) + { + tem[i] = 1.0f / nb_classes; + } + var priors = np.log(np.array(tem)); // posterior log probability, log P(c) + log P(x|c) - var joint_likelihood = tf.add(new Tensor(priors), cond_probs); + var joint_likelihood = tf.add(ops.convert_to_tensor(priors, TF_DataType.TF_FLOAT), cond_probs); // normalize to get (log)-probabilities var norm_factor = tf.reduce_logsumexp(joint_likelihood, new int[] { 1 }, true); diff --git a/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj b/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj index 912dc91c..c2de3395 100644 --- a/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj +++ b/test/TensorFlowNET.Examples/TensorFlowNET.Examples.csproj @@ -14,6 +14,7 @@ +