[转]在C#中像Python一样编写TensorFlow机器学习代码

 

机器学习是一个令人激动人心的领域,一直有新的技术突破。研究人员不断推动机器智能的提升,教机器如何听说读写——这些曾经是我们人类专属的技能。机器学习的首选语言是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
版权声明:本文为作者原创文章,转载请附上博文链接!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285624.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【土地评价与土地管理】教案 第一章:土地评价要素的选择

文章目录 1.1 土地构成要素与其农业利用1、光能条件2、热量条件3、降水条件1.1 土地构成要素与其农业利用 1、光能条件  光能是绿色植物进行光合作用和生物运动发展的主要能源  太阳辐射、日照时数  太阳辐射量随地域和季节变化较大,导致了土地利用的多样性和土地资源…

Blazor University (33)表单 —— EditContext、FieldIdentifiers

原文链接&#xff1a;https://blazor-university.com/forms/editcontext-fieldidentifiers-and-fieldstate/EditContext、FieldIdentifiers 和 FieldState请注意&#xff0c;对于那些希望了解 Blazor 如何“在后台”工作的人来说&#xff0c;这是一个高级主题。无需了解此信息即…

团队项目开发篇章8

例会时间&#xff1a;2016.11.3 整理&#xff1a;姬索肇 例会照片 每个人的工作 任务分配 我们今天与王鹿鸣学长和李云涛学长针对团队开发过程中遇到的问题进行了讨论&#xff0c;非常感谢学长们的热心帮助&#xff0c;同时我们也被他们强大的编程能力所折服~ 在这里为学长们点…

【地理信息系统GIS】教案(七章全)第一章:地理信息系统概述

文章目录 第一节 GIS基本概念第二节 GIS的组成第三节 GIS的功能第四节 GIS的发展第一节 GIS基本概念 1.1 GIS基本概念 1、信息 是用文字、数字、符号、语言、图象、图形等介质来表达事件、事物或现象等的内容、数量和特征,从而向人们(或系统)提供关于现实世界新的事实和知…

表达式的动态解析和计算,Flee用起来真香

前言在很多项目中经常会出现需要动态解析表达式和计算的场景&#xff0c;比如一些自动审核规则&#xff0c;或者是一些变量的值通过维护的公式在运行过程中动态算出&#xff1b;由于场景需求&#xff0c;都需要比较灵活的配置对应的表达式&#xff0c;然后希望在需要的时候能根…

C语言九十五之实现经典的反转数组(通过指针或数组下标操作)

✅作者简介&#xff1a;大家好我是码玛莎拉蒂&#xff0c;CSDN博客专家&#x1f947;&#x1f947;&#x1f947; &#x1f4c3;个人主页&#xff1a;个人主页 &#x1f525;系列专栏&#xff1a;C语言试题200例 &#x1f4ac;推荐一款模拟面试、刷题神器&#x1f449; 点击跳转…

Linux下使用shell实现上传linux下某个目录下所有文件到ftp

首先我们需要搞清楚单个文件怎么上传&#xff0c;把这个单文件上传到ftp上的实现命名为一个:upload_to_ftp_command.sh 之后&#xff0c;需要弄清楚怎么实现遍历一个目录下的所有文件的&#xff0c;把这个遍历某个目录下的文件实现命名为&#xff1a;foeach_directory_and_uplo…

[转]Mysql数据库开发的36条原则

前言 这些原则都是经历过实战总结而成 每一条原则背后都是血淋淋的教训 这些原则主要是针对数据库开发人员&#xff0c;在开发过程中务必注意 总是在灾难发生后&#xff0c;才想起容灾的重要性&#xff1b; 总是在吃过亏以后&#xff0c;才记得曾有人提醒过。 一、核心原则…

大话领域驱动设计——表示层及其他

概述表示层又称用户界面层&#xff0c;包含应用程序的页面、组件等UI元素。服务层提供项目的HTTP API接口&#xff0c;包含MVC Controller和相关组件。ABP框架虽然在表示层提供了不少组件&#xff0c;但是这些和DDD本身没有多少关系。而且随着前后端分离架构的流行&#xff0c;…

Windows10家庭中文版没有本地策略选项完美解决方案

Win+R,在运行中输入:secpol.msc,查看安全设置是否打开,如下图所示。 组策略对于优化和维护Windows系统来说十分重要。众所周知,Windows 10家庭版中并不包含组策略,对于使用家庭版Windows的朋友来说,十分不方便。 通常情况下,如果策略组没有打开的话,在安装CAD等软件时…

【ArcGIS风暴】栅格计算器(Raster Calculator)运算出现错误问题及解决方案汇总

栅格计算器(Raster Calculator) 是一种空间分析函数工具,可以输入地图代数表达式,使用运算符和函数来做数学计算,建立选择查询,或键入地图代数语法。只有熟练的运用并记忆一些常用的公式,才能很好的运用栅格计算器。在使用的过程中,容易出现这样那样的问题,本文就把栅…

为 ServiceCollection 实现装饰器模式

为 ServiceCollection 实现装饰器模式Intro在二十四种设计模式中&#xff0c;有一个模式叫做装饰器模式一般用来动态地给一个对象添加一些额外的职责&#xff0c;就增加功能来说&#xff0c;装饰模式比生成子类更为灵活&#xff0c;有更好的扩展性&#xff0c;我们也可以借助 D…

手把手教你启用Win10的Linux子系统 Ubuntu

1、打开“开发者选项” 2、启用“执行 Linux 程序的windows 子系统” 3、应用商店下载安装Ubuntu 附&#xff1a;ubuntu的一些命令及查看已安装软件包的命令 // 系统 # uname -a # 查看内核/操作系统/CPU信息 # head -n 1 /etc/issue # 查看操作系统版本 # cat…

【地理信息系统GIS】教案(七章全)第五章:空间数据查询与空间分析

目录 第一节 空间数据查询第二节 缓冲区分析第三节 叠置分析第四节 网络分析第五节 DEM建立及分析第一节 空间数据查询 1.1 空间数据查询 1、空间数据查询的含义 从空间数据库中找出所有满足属性约束条件和空间约束条件的地理对象。 空间数据查询的一般过程 2、空间数据查询…

[转]5分钟实现Android中更换头像功能

5分钟实现Android中更换头像功能 写在前面&#xff1a; 更换头像这个功能在用户界面几乎是100%出现的。通过拍摄照片或者调用图库中的图片&#xff0c;并且进行剪裁&#xff0c;来进行头像的设置。 功能相关截图如下&#xff1a; 下面我们直接看看完整吧&#xff1a; public cl…

Excel VBA窗体上打印系统时间print now出错原因及解决方案

如图所示,需要在窗体上显示当前系统时间: 首先,我们看一下now函数的原型: Now 函数   语法:Now   说明:返回一个 Variant (Date),根据计算机系统设置的日期和时间来指定日期和时间。   示例: Private Sub CommandButton1_Click()Dim a As Varianta = NowMsgBox…

(第九周)团队项目14

项目名&#xff1a;食物链教学工具 组名&#xff1a;奋斗吧兄弟 组长&#xff1a;黄兴 组员&#xff1a;李俞寰、杜桥、栾骄阳、王东涵 代码地址&#xff1a;HTTPS: https://git.coding.net/li_yuhuan/FoodChain.git SSH: gitgit.coding.net:li_yuhuan/FoodChain.git SCRUM会议…

为什么 C# 访问 null 字段会抛异常?

一&#xff1a;背景 1. 一个有趣的话题最近在看 硬件异常 相关知识&#xff0c;发现一个有意思的空引用异常问题&#xff0c;拿出来和大家分享一下&#xff0c;为了方便讲述&#xff0c;先上一段有问题的代码。namespace ConsoleApp2 {internal class Program{static Person pe…

C语言试题一百之输入某年某月某日,判断这一天是这一年的第几天

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:输入某年某月某日,判断这一天是这一年的第几天? 分析: 以 3 月 5 日为例,应该先把…

[转]Java学习路线图(完整详细2019版)

一门永不过时的编程语言——Java 软件开发。 Java编程语言占比&#xff1a; 据官方数据统计&#xff0c;在全球编程语言工程师的数量上&#xff0c;Java编程语言以1000万的程序员数量位居首位。 而且很多软件的开发都离不开Java编程&#xff0c;因此其程序员的数量最多。而在…