c# Http请求之HttpClient
利用HttpClient进行Http请求,基于此,简单地封装了下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
using System; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Text; namespace ConsoleApplication2 { public class HTTPClientHelper { private static readonly HttpClient HttpClient; static HTTPClientHelper() { var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.None }; HttpClient = new HttpClient(handler); } /// <summary> /// get请求,可以对请求头进行多项设置 /// </summary> /// <param name="paramArray"></param> /// <param name="url"></param> /// <returns></returns> public static string GetResponseByGet(List<KeyValuePair<string,string>> paramArray, string url) { string result = ""; var httpclient = HTTPClientHelper.HttpClient; url = url + "?" + BuildParam(paramArray); var response = httpclient.GetAsync(url).Result; if (response.IsSuccessStatusCode) { Stream myResponseStream = response.Content.ReadAsStreamAsync().Result; StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8")); result = myStreamReader.ReadToEnd(); myStreamReader.Close(); myResponseStream.Close(); } return result; } public static string GetResponseBySimpleGet(List<KeyValuePair<string,string>> paramArray, string url) { var httpclient = HTTPClientHelper.HttpClient; url = url + "?" + BuildParam(paramArray); var result = httpclient.GetStringAsync(url).Result; return result; } public static string HttpPostRequestAsync(string Url, List<KeyValuePair<string, string>> paramArray, string ContentType = "application/x-www-form-urlencoded") { string result = ""; var postData = BuildParam(paramArray); var data = Encoding.ASCII.GetBytes(postData); try { using (HttpClient http = new HttpClient()) { http.DefaultRequestHeaders.Add("User-Agent", @"Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"); http.DefaultRequestHeaders.Add("Accept", @"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); HttpResponseMessage message = null; using (Stream dataStream = new MemoryStream(data ?? new byte[0])) { using (HttpContent content = new StreamContent(dataStream)) { content.Headers.Add("Content-Type", ContentType); var task = http.PostAsync(Url, content); message = task.Result; } } if (message != null && message.StatusCode == System.Net.HttpStatusCode.OK) { using (message) { result = message.Content.ReadAsStringAsync().Result; } } } } catch (Exception ex) { Console.WriteLine(ex.Message); } return result; } private static string Encode(string content, Encoding encode = null) { if (encode == null) return content; return System.Web.HttpUtility.UrlEncode(content, Encoding.UTF8); } private static string BuildParam(List<KeyValuePair<string, string>> paramArray, Encoding encode = null) { string url = ""; if (encode == null) encode = Encoding.UTF8; if (paramArray != null && paramArray.Count > 0) { var parms = ""; foreach (var item in paramArray) { parms += string.Format("{0}={1}&", Encode(item.Key, encode), Encode(item.Value, encode)); } if (parms != "") { parms = parms.TrimEnd('&'); } url += parms; } return url; } } } |
有关更多的Http请求,请看这里:https://github.com/wangqiang3311/HttpRequestDemo from:http://www.cnblogs.com/wangqiang3311/p/8991214.html
View DetailsC# 中使用System.Net.Http.HttpClient 模拟登录博客园 (GET/POST)
一、 System.Net.Http.HttpClient简介 System.Net.Http 是微软.net4.5中推出的HTTP 应用程序的编程接口, 微软称之为“现代化的 HTTP 编程接口”, 主要提供如下内容: 1. 用户通过 HTTP 使用现代化的 Web Service 的客户端组件; 2. 能够同时在客户端与服务端同时使用的 HTTP 组件(比如处理 HTTP 标头和消息), 为客户端和服务端提供一致的编程模型。 个人看来是抄袭apache http client ,目前网上用的人好像不多,个人认为使用httpclient最大的好处是:不用自己管理cookie,只要负责写好请求即可。 由于网上资料不多,这里借登录博客园网站做个简单的总结其get和post请求的用法。 查看微软的api可以发现其属性方法:http://msdn.microsoft.com/zh-cn/library/system.net.http.httpclient.aspx 由其api可以看出如果想设置请求头只需要在DefaultRequestHeaders里进行设置 创建httpcliet可以直接new HttpClient() 发送请求可以按发送方式分别调用其方法,如get调用GetAsync(Uri),post调用PostAsync(Uri, HttpContent),其它依此类推。。。 二、实例(模拟post登录博客园) 首先,需要说明的是,本实例环境是win7 64位+vs 2013+ .net 4.5框架。 1.使用vs2013新建一个控制台程序,或者窗体程序,如下图所示: 2.必须引入System.Net.Http框架,否则将不能使用httpclient 3.实现代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace ClassLibrary1 { public class Class1 { private static String dir = @"C:\work\"; /// <summary> /// 写文件到本地 /// </summary> /// <param name="fileName"></param> /// <param name="html"></param> public static void Write(string fileName, string html) { try { FileStream fs = new FileStream(dir + fileName, FileMode.Create); StreamWriter sw = new StreamWriter(fs, Encoding.Default); sw.Write(html); sw.Close(); fs.Close(); }catch(Exception ex){ Console.WriteLine(ex.StackTrace); } } /// <summary> /// 写文件到本地 /// </summary> /// <param name="fileName"></param> /// <param name="html"></param> public static void Write(string fileName, byte[] html) { try { File.WriteAllBytes(dir + fileName, html); } catch (Exception ex) { Console.WriteLine(ex.StackTrace); } } /// <summary> /// 登录博客园 /// </summary> public static void LoginCnblogs() { HttpClient httpClient = new HttpClient(); httpClient.MaxResponseContentBufferSize = 256000; httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36"); String url = "http://passport.cnblogs.com/login.aspx"; HttpResponseMessage response = httpClient.GetAsync(new Uri(url)).Result; String result = response.Content.ReadAsStringAsync().Result; String username = "hi_amos"; String password = "密码"; do { String __EVENTVALIDATION = new Regex("id=\"__EVENTVALIDATION\" value=\"(.*?)\"").Match(result).Groups[1].Value; String __VIEWSTATE = new Regex("id=\"__VIEWSTATE\" value=\"(.*?)\"").Match(result).Groups[1].Value; String LBD_VCID_c_login_logincaptcha = new Regex("id=\"LBD_VCID_c_login_logincaptcha\" value=\"(.*?)\"").Match(result).Groups[1].Value; //图片验证码 url = "http://passport.cnblogs.com" + new Regex("id=\"c_login_logincaptcha_CaptchaImage\" src=\"(.*?)\"").Match(result).Groups[1].Value; response = httpClient.GetAsync(new Uri(url)).Result; Write("amosli.png", response.Content.ReadAsByteArrayAsync().Result); Console.WriteLine("输入图片验证码:"); String imgCode = "wupve";//验证码写到本地了,需要手动填写 imgCode = Console.ReadLine(); //开始登录 url = "http://passport.cnblogs.com/login.aspx"; List<KeyValuePair<String, String>> paramList = new List<KeyValuePair<String, String>>(); paramList.Add(new KeyValuePair<string, string>("__EVENTTARGET", "")); paramList.Add(new KeyValuePair<string, string>("__EVENTARGUMENT", "")); paramList.Add(new KeyValuePair<string, string>("__VIEWSTATE", __VIEWSTATE)); paramList.Add(new KeyValuePair<string, string>("__EVENTVALIDATION", __EVENTVALIDATION)); paramList.Add(new KeyValuePair<string, string>("tbUserName", username)); paramList.Add(new KeyValuePair<string, string>("tbPassword", password)); paramList.Add(new KeyValuePair<string, string>("LBD_VCID_c_login_logincaptcha", LBD_VCID_c_login_logincaptcha)); paramList.Add(new KeyValuePair<string, string>("LBD_BackWorkaround_c_login_logincaptcha", "1")); paramList.Add(new KeyValuePair<string, string>("CaptchaCodeTextBox", imgCode)); paramList.Add(new KeyValuePair<string, string>("btnLogin", "登 录")); paramList.Add(new KeyValuePair<string, string>("txtReturnUrl", "http://home.cnblogs.com/")); response = httpClient.PostAsync(new Uri(url), new FormUrlEncodedContent(paramList)).Result; result = response.Content.ReadAsStringAsync().Result; Write("myCnblogs.html",result); } while (result.Contains("验证码错误,麻烦您重新输入")); Console.WriteLine("登录成功!"); //用完要记得释放 httpClient.Dispose(); } public static void Main() { LoginCnblogs(); } } |
代码分析: 首先,从Main函数开始,调用LoginCnblogs方法; 其次,使用GET方法:
1 2 |
HttpResponseMessage response = httpClient.GetAsync(new Uri(url)).Result; String result = response.Content.ReadAsStringAsync().Result; |
再者,使用POST方法:
1 2 3 4 5 |
List<KeyValuePair<String, String>> paramList = new List<KeyValuePair<String, String>>(); paramList.Add(new KeyValuePair<string, string>("__EVENTTARGET", "")); .... response = httpClient.PostAsync(new Uri(url), new FormUrlEncodedContent(paramList)).Result; result = response.Content.ReadAsStringAsync().Result; |
最后,注意其返回值可以是string,也可以是byte[],和stream的方式,这里看你需要什么吧。 4.登录成功后的截图 1).使用浏览器登录后的截图: 2).使用Httpcliet登录后的截图: 总结,可以发现C#中HttpClient的用法和Java中非常相似,所以,说其抄袭确实不为过。 from:https://www.cnblogs.com/amosli/p/3918538.html
View DetailsC# HttpClient设置cookies的两种办法 (转发)
一般有两种办法 第一种handler.UseCookies=true(默认为true),默认的会自己带上cookies,例如
1 2 3 4 5 6 7 8 9 10 11 12 |
var handler = new HttpClientHandler() { UseCookies = true }; var client = new HttpClient(handler);// { BaseAddress = baseAddress }; client.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0"); client.DefaultRequestHeaders.Add("Connection", "Keep-Alive"); client.DefaultRequestHeaders.Add("Keep-Alive", "timeout=600"); var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("email", "xxxx"), new KeyValuePair<string, string>("password", "xxxx"), }); var result = await client.PostAsync("https://www.xxxx.com/cp/login", content); result.EnsureSuccessStatusCode(); |
这种情况post请求登陆成功后,重定向到别的页面,也会自动带上cookies。如果把handler.UseCookies设置为false,登陆后重定向的话不会自动带上cookies,则又会跳转到登陆页面。 第二种设置 handler.UseCookies = false时,则需要手动给headers上加入cookies.
1 2 3 4 5 6 |
var handler = new HttpClientHandler() { UseCookies = false}; var client = new HttpClient(handler);// { BaseAddress = baseAddress }; var message = new HttpRequestMessage(HttpMethod.Get, url); message.Headers.Add("Cookie", "session_id=7258abbd1544b6c530a9f406d3e600239bd788fb"); var result = await client.SendAsync(message); result.EnsureSuccessStatusCode(); |
如果使用场景是:抓取需要登陆后才能看到的网页数据,建议使用第一种,不需要设置任何cookies,httpclient会自动把登陆后的cookies放置到后面的请求中。 原贴 : http://www.cnblogs.com/xiaozhu39505/p/8033108.html from:https://www.cnblogs.com/refuge/p/8060142.html
View Details重启IIS某个站点脚本
修改siteName为需要的重启的网站名字,将代码拷入bat文件 @echo off cd c:\Windows\System32\inetsrv appcmd stop site "siteName" appcmd start site "siteName" from:https://blog.csdn.net/a980433875/article/details/52088252
View DetailsRedis 避不开的五种数据结构
Redis 中有 5 种数据结构,分别是字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set),因为使用 Redis 场景的开发中肯定是无法避开这些基础结构的,所以熟练掌握它们也就成了一项必不可少的能力。本文章精要地介绍了 Redis 的这几种数据结构,主要覆盖了它们各自的定义、基本用法与相关要点。 字符串类型 字符串是 Redis 中的最基础的数据结构,我们保存到 Redis 中的 key,也就是键,就是字符串结构的。除此之外,Redis 中其它数据结构也是在字符串的基础上设计的,可见字符串结构对于 Redis 是多么重要。 Redis 中的字符串结构可以保存多种数据类型,如:简单的字符串、JSON、XML、二进制等,但有一点要特别注意:在 Redis 中字符串类型的值最大只能保存 512 MB。 命令 下面通过命令了解一下对字符串类型的操作: 1.设置值
1 |
set key value [EX seconds] [PX milliseconds] [NX|XX] |
set 命令有几个非必须的选项,下面我们看一下它们的具体说明: EX seconds:为键设置秒级过期时间 PX milliseconds:为键设置毫秒级过期时间 NX:键必须不存在,才可以设置成功,用于添加 XX:键必须存在,才可以设置成功,用于更新 set 命令带上可选参数 NX 和 XX 在实际开发中的作用与 setnx 和 setxx 命令相同。我们知道 setnx 命令只有当 key 不存在的时候才能设置成功,换句话说,也就是同一个 key 在执行 setnx 命令时,只能成功一次,并且由于 Redis 的单线程命令处理机制,即使多个客户端同时执行 setnx 命令,也只有一个客户端执行成功。所以,基于 setnx 这种特性,setnx 命令可以作为分布式锁的一种解决方案。 而 setxx 命令则可以在安全性比较高的场景中使用,因为 set 命令执行时,会执行覆盖的操作,而 setxx 在更新 key 时可以确保该 key 已经存在了,所以为了保证 key 中数据类型的正确性,可以使用 setxx 命令。 2.获取值
1 |
get key |
3.批量设置值
1 |
mset key value |
4.批量获取值
1 |
mget key |
如果有些键不存在,那么它的值将为 nil,也就是空,并且返回结果的顺序与传入时相同。 5.计数
1 |
incr key |
incr 命令用于对值做自增操作,返回的结果分为 […]
View Details记聊天服务宕机事件
9月23日,农历8月14,中秋假期。 上午9点,领导微信语音通话说聊天服务挂了。 然后打开网站,果然挂了。 看异常日志,提示程序错误。 然后,果断回滚到上一个版本,还是错误。 然后,再恢复了前一个版本,依然不行。 连接到公司办公环境…… 那只有分析异常日志了,可异常日志记录的堆栈信息只是说那个方法错误,没有具体的信息。 果断去掉异常捕捉try-catch,编译,上线。 服务器日志有错误,已经具体到底层方法和行数了,是log4net写日志错误。 然后恢复日志模块以前的版本,不行,依然写日志错误。 没办法,动手修改这个方法,上传。 这次写日志没错了。 再看操作系统日志,这次提示redis连接对象错误,然后怀疑redis连不上了。 由于是新服务器,没有安装redis客户端;然后下载RedisDesktopManager,从国外站点下载10MB真不容易,30KB/s;然后想把办公电脑的安装程序传到服务器上,总是断开(可能公司的路由器太垃圾);试了几次不行。然后就用winrar压缩成多个小的包,终于传到服务器上了。 安装,测试,………………redis果然不通…………¥!@##@#!@#@##¥@#¥%¥&…………%& 告诉领导redis服务不通…… 领导看了阿云控制台,说忘了续费了,233233~ 续费后,测试redis通了,聊天服务也一切正常了,真折腾啊!! 此时,3个小时已经过去了……本来中秋只放了两天假,这又少了半天,早饭还没吃……不饿。 总结: 主因是redis过期没有续费的原因。 redis不通时,写log4net日志方法确实有错误。 异常日志记录的不够详细,如果记录了redis连不通异常,那就简单多了,也不用那么折腾;
View DetailsDocker for Windows 里的Shared Drives 设置不生效
昨天,帅彬同学出现了一个疑难杂症,具体的可以大致描述成:Docker中的settings里的Shared Drives 选择对应盘符后,点击Apply后无法生效,没办法选择对应盘符进行分享。 解决办法:win+R ,键入gpedit.msc,出现如下界面,找到高亮处的网络访问:本地账户的共享和安全模型,选择如图中的 经典 选项。即可。 原因分析: 由上图可以看出,大致是用户的权限问题导致。 from:https://blog.csdn.net/u012680857/article/details/77970351
View DetailsWindows下Docker查看容器IP地址
docker inspect ––format {{.NetworkSettings.IPAddress}} stupefied_turing
View Detailsvue开源项目
写在前面的 评价纯属个人主观感受,有夸张成分,只是一种表达,如有不喜请无视之。欢迎指正不足和提供更多更好的vue库,项目,方便参考和学习使用。 一、前台UI组件库 1.Element 优点:中文文档,ui种类比较全,ui设计简洁清晰 缺点:不够有特点 2.iView 优点:和element的UI很相似,有一些多的补充,可以相互替换 缺点:仍然没有什么特色 3.Vuetify 优点:时间选择器是时钟样式,比较有特色。中文文档 缺点:种类不如前面全 地址:https://vuetifyjs.com/zh-Hans/ 4.Vue-material 优点:日期选择器配色舒适,进度条样式有虚线形式,步骤条更清晰相比有创新。表单字段点击后文字会上浮 缺点:目前种类还比较少,遗憾没有时间选择器。非中文文档 5.Quasar 构建响应式网站,PWA,混合移动应用程序 打不开,应该是被墙了,无法评论,只有项目 6.Buefy 优点:时间选择器数字很大有特点 缺点:非中文文档 7.Vant 优点:移动端界面,轻量化,基本涵盖移动端交互的ui,和微信样式很像 8.At-ui 一款全新的平面UI套件,专门用于桌面应用程序 优点:颜色比较素雅,UI比较秀气 9.Vue-js-modal 关于模态框的ui库,配色和阴影上适合音乐娱乐类项目 10.Vuex-loading 等待相关进度的一些库 缺点:并不是那么好看,使用的话,最好手动调调整一下样式 11.Vue-js-grid 可移动方格子位置的库 12.Dockeron docker上的ui库,使用后再回补 13.mint-ui 优点:风格简洁,文档中移动端看的效果清晰 缺点:中文字体和间距比例上稍稍偏大 14.Keen-UI 优点:移动端框架,日期选择器比较好看。 缺点:非中文文档 15.VueCircleMenu 优点:提供各种从中间蹦跶出半圆形按钮的组件方案,主流ui库给的比较少,有了它可以不用自己写了 缺点:配色视图有点惨 16.vue-carbon 有点:很淡雅的风格,虽然颜色只有一种,但是字体和间距给的很好,一眼过去很舒服,ui相比要做的事情不会喧宾夺主。 缺点:在中国可能不是主流(国人喜欢花花绿绿,字体大大的) 17.vue-calendar 特别中国特色,排版稍稍有点拥挤,但是有农历,好评! 18.vue-datetime-picker 19.vue2-calendar 优点:日期选择器中支持自定义事件的稀缺 ★181 – 支持lunar和日期事件的日期选择器 20.vue-datepicker 日期选择器简洁大气,希望可以有匹配的时间选择器 21.vue-datepicker 优点:很小巧,没有多余的装饰,不占版面 22.vue-date-picker ★59 – VueJS日期选择器组件 23.vue-fullcalendar 大格子化日期选择器,酒店入住等游玩类网站会用到 24.vue-datepicker-simple 月份选择排版蛮特别,极少数用这么正红配色的日期选择器 ★20 – 基于vue的日期选择 25.vue-chartjs 可视化图表的vue版本,主要饼形图,条形图,雷达图等都有 缺点:样式太简,使用还需调整,相比百度的Echart还是少太多图类 26.DataVisualization 提供四个最简单的图类,比较实用 缺点:配色上背景太花,前景色饱和度太低,需要调整 ★149 – 数据可视化 27.vue-charts 样式比较好看,但目前图标类型还是太少 ★101 – 轻松渲染一个图表 28.vue-chartkick […]
View Details使用ML.NET预测纽约出租车费
有了上一篇《.NET Core玩转机器学习》打基础,这一次我们以纽约出租车费的预测做为新的场景案例,来体验一下回归模型。 场景概述 我们的目标是预测纽约的出租车费,乍一看似乎仅仅取决于行程的距离和时长,然而纽约的出租车供应商对其他因素,如额外的乘客数、信用卡而不是现金支付等,会综合考虑而收取不同数额的费用。纽约市官方给出了一份样本数据。 确定策略 为了能够预测出租车费,我们选择通过机器学习建立一个回归模型。使用官方提供的真实数据进行拟合,在训练模型的过程中确定真正能影响出租车费的决定性特征。在获得模型后,对模型进行评估验证,如果偏差在接受的范围内,就以这个模型来对新的数据进行预测。 解决方案 创建项目 看过上一篇文章的读者,就比较轻车熟路了,推荐使用Visual Studio 2017创建一个.NET Core的控制台应用程序项目,命名为TaxiFarePrediction。使用NuGet包管理工具添加对Microsoft.ML的引用。 准备数据集 下载训练数据集taxi-fare-train.csv和验证数据集taxi-fare-test.csv,数据集的内容类似为:
1 2 3 4 5 6 7 |
vendor_id,rate_code,passenger_count,trip_time_in_secs,trip_distance,payment_type,fare_amount VTS,1,1,1140,3.75,CRD,15.5 VTS,1,1,480,2.72,CRD,10.0 VTS,1,1,1680,7.8,CSH,26.5 VTS,1,1,600,4.73,CSH,14.5 VTS,1,1,600,2.18,CRD,9.5 ... |
对字段简单说明一下: 字段名 含义 说明 vendor_id 供应商编号 特征值 rate_code 比率码 特征值 passenger_count 乘客人数 特征值 trip_time_in_secs 行程时长 特征值 trip_distance 行程距离 特征值 payment_type 支付类型 特征值 fare_amount 费用 目标值 在项目中添加一个Data目录,将两份数据集复制到该目录下,对文件属性设置“复制到输出目录”。 定义数据类型和路径 首先声明相关的包引用。
1 2 3 4 5 6 7 8 9 |
using System; using Microsoft.ML.Models; using Microsoft.ML.Runtime; using Microsoft.ML.Runtime.Api; using Microsoft.ML.Trainers; using Microsoft.ML.Transforms; using System.Collections.Generic; using System.Linq; using Microsoft.ML; |
在Main函数的上方定义一些使用到的常量。
1 2 3 4 |
const string DataPath = @".\Data\taxi-fare-train.csv"; const string TestDataPath = @".\Data\taxi-fare-test.csv"; const string ModelPath = @".\Models\Model.zip"; const string ModelDirectory = @".\Models"; |
接下来定义一些使用到的数据类型,以及和数据集中每一行的位置对应关系。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
public class TaxiTrip { [Column(ordinal: "0")] public string vendor_id; [Column(ordinal: "1")] public string rate_code; [Column(ordinal: "2")] public float passenger_count; [Column(ordinal: "3")] public float trip_time_in_secs; [Column(ordinal: "4")] public float trip_distance; [Column(ordinal: "5")] public string payment_type; [Column(ordinal: "6")] public float fare_amount; } public class TaxiTripFarePrediction { [ColumnName("Score")] public float fare_amount; } static class TestTrips { internal static readonly TaxiTrip Trip1 = new TaxiTrip { vendor_id = "VTS", rate_code = "1", passenger_count = 1, trip_distance = 10.33f, payment_type = "CSH", fare_amount = 0 // predict it. actual = 29.5 }; } |
创建处理过程 创建一个Train方法,定义对数据集的处理过程,随后声明一个模型接收训练后的结果,在返回前把模型保存到指定的位置,以便以后直接取出来使用不需要再重新训练。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public static async Task<PredictionModel<TaxiTrip, TaxiTripFarePrediction>> Train() { var pipeline = new LearningPipeline(); pipeline.Add(new TextLoader<TaxiTrip>(DataPath, useHeader: true, separator: ",")); pipeline.Add(new ColumnCopier(("fare_amount", "Label"))); pipeline.Add(new CategoricalOneHotVectorizer("vendor_id", "rate_code", "payment_type")); pipeline.Add(new ColumnConcatenator("Features", "vendor_id", "rate_code", "passenger_count", "trip_distance", "payment_type")); pipeline.Add(new FastTreeRegressor()); PredictionModel<TaxiTrip, TaxiTripFarePrediction> model = pipeline.Train<TaxiTrip, TaxiTripFarePrediction>(); if (!Directory.Exists(ModelDirectory)) { Directory.CreateDirectory(ModelDirectory); } await model.WriteAsync(ModelPath); return model; } |
评估验证模型 创建一个Evaluate方法,对训练后的模型进行验证评估。
1 2 3 4 5 6 7 8 9 |
public static void Evaluate(PredictionModel<TaxiTrip, TaxiTripFarePrediction> model) { var testData = new TextLoader<TaxiTrip>(TestDataPath, useHeader: true, separator: ","); var evaluator = new RegressionEvaluator(); RegressionMetrics metrics = evaluator.Evaluate(model, testData); // Rms should be around 2.795276 Console.WriteLine("Rms=" + metrics.Rms); Console.WriteLine("RSquared = " + metrics.RSquared); } |
预测新数据 定义一个被用于预测的新数据,对于各个特征进行恰当地赋值。
1 2 3 4 5 6 7 8 9 10 11 12 |
static class TestTrips { internal static readonly TaxiTrip Trip1 = new TaxiTrip { vendor_id = "VTS", rate_code = "1", passenger_count = 1, trip_distance = 10.33f, payment_type = "CSH", fare_amount = 0 // predict it. actual = 29.5 }; } |
预测的方法很简单,prediction即预测的结果,从中打印出预测的费用和真实费用。
1 2 3 |
var prediction = model.Predict(TestTrips.Trip1); Console.WriteLine("Predicted fare: {0}, actual fare: 29.5", prediction.fare_amount); |
运行结果 到此我们完成了所有的步骤,关于这些代码的详细说明,可以参看《Tutorial: Use ML.NET to Predict New York Taxi Fares (Regression)》,只是要注意该文中的部分代码有误,由于使用到了C# 7.1的语法特性,本文的代码是经过了修正的。完整的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
using System; using Microsoft.ML.Models; using Microsoft.ML.Runtime; using Microsoft.ML.Runtime.Api; using Microsoft.ML.Trainers; using Microsoft.ML.Transforms; using System.Collections.Generic; using System.Linq; using Microsoft.ML; using System.Threading.Tasks; using System.IO; namespace TaxiFarePrediction { class Program { const string DataPath = @".\Data\taxi-fare-train.csv"; const string TestDataPath = @".\Data\taxi-fare-test.csv"; const string ModelPath = @".\Models\Model.zip"; const string ModelDirectory = @".\Models"; public class TaxiTrip { [Column(ordinal: "0")] public string vendor_id; [Column(ordinal: "1")] public string rate_code; [Column(ordinal: "2")] public float passenger_count; [Column(ordinal: "3")] public float trip_time_in_secs; [Column(ordinal: "4")] public float trip_distance; [Column(ordinal: "5")] public string payment_type; [Column(ordinal: "6")] public float fare_amount; } public class TaxiTripFarePrediction { [ColumnName("Score")] public float fare_amount; } static class TestTrips { internal static readonly TaxiTrip Trip1 = new TaxiTrip { vendor_id = "VTS", rate_code = "1", passenger_count = 1, trip_distance = 10.33f, payment_type = "CSH", fare_amount = 0 // predict it. actual = 29.5 }; } public static async Task<PredictionModel<TaxiTrip, TaxiTripFarePrediction>> Train() { var pipeline = new LearningPipeline(); pipeline.Add(new TextLoader<TaxiTrip>(DataPath, useHeader: true, separator: ",")); pipeline.Add(new ColumnCopier(("fare_amount", "Label"))); pipeline.Add(new CategoricalOneHotVectorizer("vendor_id", "rate_code", "payment_type")); pipeline.Add(new ColumnConcatenator("Features", "vendor_id", "rate_code", "passenger_count", "trip_distance", "payment_type")); pipeline.Add(new FastTreeRegressor()); PredictionModel<TaxiTrip, TaxiTripFarePrediction> model = pipeline.Train<TaxiTrip, TaxiTripFarePrediction>(); if (!Directory.Exists(ModelDirectory)) { Directory.CreateDirectory(ModelDirectory); } await model.WriteAsync(ModelPath); return model; } public static void Evaluate(PredictionModel<TaxiTrip, TaxiTripFarePrediction> model) { var testData = new TextLoader<TaxiTrip>(TestDataPath, useHeader: true, separator: ","); var evaluator = new RegressionEvaluator(); RegressionMetrics metrics = evaluator.Evaluate(model, testData); // Rms should be around 2.795276 Console.WriteLine("Rms=" + metrics.Rms); Console.WriteLine("RSquared = " + metrics.RSquared); } static async Task Main(string[] args) { PredictionModel<TaxiTrip, TaxiTripFarePrediction> model = await Train(); Evaluate(model); var prediction = model.Predict(TestTrips.Trip1); Console.WriteLine("Predicted fare: {0}, actual fare: 29.5", prediction.fare_amount); } } } |
不知不觉我们的ML.NET之旅又向前进了一步,是不是对于使用.NET Core进行机器学习解决现实生活中的问题更有兴趣了?请保持关注吧。 from:http://www.cnblogs.com/BeanHsiang/p/9017618.html
View Details