机器学习是一个令人激动人心的领域,一直有新的技术突破。研究人员不断推动机器智能的提升,教机器如何听说读写——这些曾经是我们人类专属的技能。机器学习的首选语言是Python,最受欢迎的库是Google的TensorFlow。几乎所有的代码示例都是用Python编写的,并且依赖于TensorFlow和NumPy库。对于C#和.NET的开发人员来说,我们在面临着一个严峻的选择:要么学习Python,要么使用NET机器学习库,并从头开始精心编写我们自己的C#代码 。
事实上,这就是我在机器学习课程中常用的策略。我研究了许多使用Keras和TensorFlow的Python代码,然后我从头开始编写自己的C#代码,使用原生的CNTK和ML.NET库代替。这种方法很有效,但它也有一些缺点:
- 我的学生习惯于.NET,这些编码技巧不容易转移到Python。
- CNTK和ML.NET不支持某些TensorFlow功能,因此我必须使用Python代码向C#开发人员演示它们。
我一直在努力在.NET中编写机器学习库,模仿Python的API和编码风格,如NativeKeras和KerasSharp,但这些项目不再处于积极开发的阶段。我一直在寻找一个全面的.NET库,它完全模仿了如何用Python编写机器学习代码,终于我发现了她——SciSharp。SciSharp正在为数据科学,机器学习和人工智能构建一个.NET开源生态系统,其理念是C#机器学习代码应该像对应的Python代码一样尽可能地语法,与编程的感觉。
看看下面的例子 - 这是TensorFlow中的简单线性回归演示。 Python代码在左侧,相应的C#代码在右侧:
右边的代码看起来像Python,但它是实际的C#代码。 它使用一个名为TesorFlow.NET的包装器在幕后调用真正的TensorFlow库。请注意,我们已经有了TensorFlow包装器; 几年前,Xamarin创始人米格尔大神建造了优秀的TensorFlowSharp。 但是,他的库只暴露了低级别的TensorFlow API。 相比之下,SciSharp库神奇地暴露了所有TensorFlow,包括高级图形构建功能。
TensorFlow在很大程度上依赖于NumPy,这是一个高性能的Python数学库,可以在内存中处理非常大的数据数组。 因此,SciSharp团队开发了自己的版本NumSharp,这是NumPy到C#的端口。
NumSharp遵循与原始NumPy完全相同的编码风格。 使用左侧的Python代码和右侧的相应C#代码查看此示例:同样,右边的代码遵循与Python相同的语法约定和API样式,但它实际上是C#代码。
SciSharp团队在这里取得了一项重大成就。 使用TensorFlow.NET和NumSharp,我们实际上可以使用Python代码示例,将它们复制并粘贴到C#文件中,然后只需稍作修改即可运行它们——这为.NET开发人员打开了完整的机器学习生态系统。
我决定采用SciSharp。查看以下说明,以便在C#中启动并运行您自己的TensorFlow代码。我将构建一个简单的线性回归演示,它适合一些样本数据的回归线。
让我们开始吧。以下是在.NET Core中设置新控制台项目的方法:
$ dotnet new console -o LinearRegression
$ cd LinearRegression
接下来,我需要安装我需要的软件包:
$ dotnet add package TensorFlow.NET
就这样简单!这将安装TensorFlow.NET包,它也将自动拉入NumSharp。该软件包还安装了Microsoft.ML.TensorFlow.Redist
,它是本机TensorFlow库的跨平台安装程序。这将在Windows,Linux和OS / X上为您设置一切。
现在我准备开始编码了。这是Program.cs的上半部分应该是这样的:
using System;
using NumSharp;
using Tensorflow;
using static Tensorflow.Python;namespace LinearRegression
{/// <summary>/// The main program class/// </summary>public class Program{/// <summary>/// The main program entry point/// </summary>/// <param name="args">The command line arguments</param>public static void Main(string[] args){// load the datavar dataX = np.array(3.3f, 4.4f, 5.5f, 6.71f, 6.93f, 4.168f, 9.779f, 6.182f, 7.59f, 2.167f,7.042f, 10.791f, 5.313f, 7.997f, 5.654f, 9.27f, 3.1f);var dataY = np.array(1.7f, 2.76f, 2.09f, 3.19f, 1.694f, 1.573f, 3.366f, 2.596f, 2.53f, 1.221f,2.827f, 3.465f, 1.65f, 2.904f, 2.42f, 2.94f, 1.3f);var samples = dataX.shape[0];// the rest of the code goes here...}}
}
这是一个简单的.NET Core控制台应用程序。 请注意使用训练数据设置NumPy数组的np.array
方法。 shape [0]调用检索数组的长度,就像在Python中一样。现在我将在TensorFlow中设置一个简单的线性回归模型:
此代码调用tf.placeholder
来设置模型输入和输出:X表示输入数据,Y表示输出数据。
以下两个调用tf.Variable
设置权重和偏差模型变量。 这些变量组合成一个模型如下:
读者会发现这只是线性回归的等式。 TensorFlow将在训练期间调整W和b变量以找到完美的回归线。
最后,代码在损失变量中设置了一个损失函数。 损失函数是一种表达式,其值在训练期间需要最小化。 我将使用均方误差或MSE:
这只是模型预测与实际值之差的平方和。接下来,我将训练这个模型1000次:
// use these training parameters
var epochs = 1000;
var learningRate = 0.01f;
var displayEvery = 50;// use a gradient descent optimizer
var optimizer = tf.train.GradientDescentOptimizer(learningRate).minimize(loss);// train the model
var init = tf.global_variables_initializer();
with(tf.Session(), sess =>
{sess.run(init);// run training epochsConsole.WriteLine("Training model...");for (int epoch = 0; epoch < epochs; epoch++){foreach (var (x, y) in zip<float>(dataX, dataY)){sess.run(optimizer, new FeedItem(X, x),new FeedItem(Y, y));}// display intermittent resultsif ((epoch + 1) % displayEvery == 0){var lossValue = sess.run(loss, new FeedItem(X, dataX), new FeedItem(Y, dataY));Console.WriteLine($" epoch: {epoch + 1}\tMSE = {lossValue}\tW = {sess.run(W)}\tb = {sess.run(b)}");}}// show final training lossvar trainingLoss = sess.run(loss,new FeedItem(X, dataX),new FeedItem(Y, dataY));Console.WriteLine($" Final MSE = {trainingLoss}");// the rest of the code goes here...
});
代码设置GradientDescentOptimizer
以最小化损失函数,并使用tf.Session()
启动TensorFlow会话。TensorFlow中的所有内容都需要调用tf.run()
来执行。所以我首先设置了一个global_variables_initializer
来初始化模型,然后运行它。然后我运行优化器1000个时期来训练模型,每50个时期我运行损失函数并显示中间训练损失。循环完成后,我再次运行损失功能并显示最终的训练损失。
我现在有一个训练有素的好模型,是时候在一些新数据上测试这个模型:
// load validation data
var testDataX = np.array(6.83f, 4.668f, 8.9f, 7.91f, 5.7f, 8.7f, 3.1f, 2.1f);
var testDataY = np.array(1.84f, 2.273f, 3.2f, 2.831f, 2.92f, 3.24f, 1.35f, 1.03f);
var validationSamples = testDataX.shape[0];// validate the model
Console.WriteLine("Validating model...");
var validationLoss = tf.reduce_sum(tf.pow(model - Y, 2.0f)) / validationSamples;
var lossValue2 = sess.run(validationLoss, new FeedItem(X, testDataX), new FeedItem(Y, testDataY));
Console.WriteLine($" Validation loss = {lossValue2}");
代码调用np.array
来设置新的验证数据,并设置一个新的validationLoss
函数来在验证期间计算MSE。然后它在验证数据上运行此损失函数,并在控制台上显示验证丢失。就是这样。这是TensorFlow中的完整线性回归演示。
此代码将在所有主要操作系统上运行 - Windows,Linux和OS / X.您可以在控制台上运行代码,如下所示:
$ dotnet run
或者通过点击F5在Visual Studio Code中。这是在最新版本的VS Code中在我的Mac上运行的应用程序:
这是在终端的命令行上运行的相同应用程序:
经过1000个训练时期后,我最终损失了0.1548。完全训练的模型在验证数据上的损失为0.1572。
这是一个最初用Python编写的TensorFlow线性回归演示,现在移植到C#,只有很少的语法更改。
有数千个类似的代码示例,现在它们都可供C#开发人员访问。
你意如何?准备好开始用TensorFlow.NET和NumSharp编写C#机器学习应用了吗?
作者:Mark Farragher
英文版地址:https://medium.com/machinelearningadvantage/run-tensorflow-machine-learning-code-in-c-with-almost-no-changes-77f7b629389
---------------------
作者:SciSharp Stack
来源:CSDN
原文:https://blog.csdn.net/SciSharp/article/details/100223186
版权声明:本文为作者原创文章,转载请附上博文链接!