目录

让我们预测房地产价格!

分析训练数据

分析列数据类型

数字列

分类列

把他们聚在一起

构建神经网络

提供数据

是时候放下梯度了

提交

总结

链接


这是一系列关于我作为 .NET 开发人员进入Kaggle竞赛黑暗森林的持续旅程的系列文章。

在这篇文章和接下来的文章中,我将关注(几乎)纯神经网络。这意味着,将有意跳过数据集准备中大部分无聊的部分,例如填充缺失值、特征选择、异常值分析等。

技术栈将是C#+TensorFlow tf.keras API。截至今天,它还将需要Windows。未来文章中的大型模型可能需要合适的GPU来保证训练时间保持理智。

让我们预测房地产价格!

房价对新手来说是一场激烈的竞争。它的数据集很小,没有特殊的规则,公开排行榜有很多参与者,每天最多可以提交4个条目。

在Kaggle上注册,如果您还没有注册,请加入本次比赛并下载数据。目标是预测test.csv条目的销售价格(SalePrice列)。存档包含train.csv,其中包含大约1500个具有已知销售价格的条目以供训练。在进入神经网络之前,我们将从加载dataset开始,并对其进行一些探索。

分析训练数据

我是说我们会跳过数据集准备吗?我撒了谎!你必须至少看一次。

令我惊讶的是,我没有找到在.NET标准类库中加载.csv文件的简单方法,所以我安装了一个名为CsvHelper的NuGet包。为了简化数据操作,我还得到了我最喜欢的新LINQ扩展包MoreLinq。

static DataTable LoadData(string csvFilePath) {var result = new DataTable();using (var reader = new CsvDataReader(new CsvReader(new StreamReader(csvFilePath)))) {result.Load(reader);}return result;
}

利用DataTable训练数据操作是,实际上,一个坏主意。

ML.NET应该具有.csv加载和许多数据准备和探索操作。然而,当我刚刚参加房价竞赛时,它还没有为那个特殊目的做好准备。

数据看起来像这样(只有几行和几列):

ID

子类

分区

地段前台

地段面积

1

60

RL

65

8450

2

20

RL

80

9600

3

60

RL

68

11250

4

70

RL

60

9550

加载数据后,我们需要删除该Id列,因为它实际上与房价无关:

var trainData = LoadData("train.csv");
trainData.Columns.Remove("Id");

分析列数据类型

DataTable不会自动推断列的数据类型,并假设它都是string。所以下一步是确定我们实际拥有什么。对于每一列,我计算了以下统计信息:不同值的数量,其中有多少是整数,有多少是浮点数(包含所有辅助方法的源代码将在文章末尾链接):

var values = rows.Select(row => (string)row[column]);
double floats = values.Percentage(v => double.TryParse(v, out _));
double ints = values.Percentage(v => int.TryParse(v, out _));
int distincts = values.Distinct().Count();

数字列

事实证明,大多数列实际上是int,但由于神经网络主要处理浮点数,我们无论如何都会将它们转换为double。

分类列

其他列描述了待售房产所属的类别。它们都没有太多不同的值,这很好。要将它们用作我们未来神经网络的输入,它们也必须转换为double。

最初,我只是将数字从0到分配distinctValueCount-1给它们,但这没有多大意义,因为实际上没有从“Facade: Blue”到“Facade: Green” 再到 “ Facade: White”的进展。很早时,我将其更改为所谓的one-hot encoding,其中每个唯一值都有一个单独的输入列。例如,“Facade: Blue”变成[1,0,0],“Facade: White”变成[0,0,1]。

把他们聚在一起

CentralAir: 2 values, ints: 0.00%, floats: 0.00%
Street: 2 values, ints: 0.00%, floats: 0.00%
Utilities: 2 values, ints: 0.00%, floats: 0.00%
....
LotArea: 1073 values, ints: 100.00%, floats: 100.00%Many value columns:
Exterior1st: AsbShng, AsphShn, BrkComm, BrkFace, CBlock, CemntBd, HdBoard, ImStucc, MetalSd, Plywood, Stone, Stucco, VinylSd, Wd Sdng, WdShing
Exterior2nd: AsbShng, AsphShn, Brk Cmn, BrkFace, CBlock, CmentBd, HdBoard, ImStucc, MetalSd, Other, Plywood, Stone, Stucco, VinylSd, Wd Sdng, Wd Shng
Neighborhood: Blmngtn, Blueste, BrDale, BrkSide, ClearCr, CollgCr, Crawfor, Edwards, Gilbert, IDOTRR, MeadowV, Mitchel, NAmes, NoRidge, NPkVill, NridgHt, NWAmes, OldTown, Sawyer, SawyerW, Somerst, StoneBr, SWISU, Timber, Veenkernon-parsable floats
GarageYrBlt: NA
LotFrontage: NA
MasVnrArea: NAfloat ranges:
BsmtHalfBath: 0...2
HalfBath: 0...2
...
GrLivArea: 334...5642
LotArea: 1300...215245

考虑到这一点,我构建了以下ValueNormalizer,它获取有关列内值的一些信息,并返回一个函数,该函数将值 (astring) 转换为神经网络 ( double[])的数字特征向量:

static Func<string, double[]> ValueNormalizer(double floats, IEnumerable<string> values) {if (floats > 0.01) {double max = values.AsDouble().Max().Value;return s => new[] { double.TryParse(s, out double v) ? v / max : -1 };} else {string[] domain = values.Distinct().OrderBy(v => v).ToArray();return s => new double[domain.Length+1].Set(Array.IndexOf(domain, s)+1, 1);}
}

现在我们已经将数据转换成适合神经网络的格式。是时候进行构建了。

构建神经网络

如果您已经安装了Python 3.6和TensorFlow 1.10.x,您只需要:

<PackageReference Include="Gradient" Version="0.1.10-tech-preview4" />

在您的现代.csproj文件中。否则,请参阅Gradient 手册进行初始设置。

一旦包启动并运行,我们就可以创建我们的第一个浅层深度网络。

using tensorflow;
using tensorflow.keras;
using tensorflow.keras.layers;
using tensorflow.train;...var model = new Sequential(new Layer[] {new Dense(units: 16, activation: tf.nn.relu_fn),new Dropout(rate: 0.1),new Dense(units: 10, activation: tf.nn.relu_fn),new Dense(units: 1, activation: tf.nn.relu_fn),
});model.compile(optimizer: new AdamOptimizer(), loss: "mean_squared_error");

这将创建一个具有3个神经元层和一个dropout层的未经训练的神经网络,有助于防止过度拟合。

tf.nn.relu_fn是我们神经元的激活函数。众所周知,ReLU在深度网络中运行良好,因为它解决了梯度消失问题:当误差从深度网络中的输出层传播回来时,原始非线性激活函数的导数往往变得非常小。这意味着,靠近输入的层只会略微调整,这会显着减慢深度网络的训练速度。

Dropout是神经网络中的一个特殊功能层,它实际上不包含神经元本身。相反,它通过获取每个单独的输入进行操作,并随机将其替换为0自输出(否则,它只会传递原始值)。通过这样做,它有助于防止在小dataset中对不太相关的特征进行过度拟合。例如,如果我们没有删除Id列,网络可能已经记住了<Id>-><SalePrice>精确映射,这将使我们在训练集上具有100%的准确度,但在任何其他数据上的数字完全不相关。为什么我们需要辍学?我们的训练数据只有约1500个示例,而我们构建的这个微型神经网络有>1800个可调权重。如果它是一个简单的多项式,它可以匹配价格函数,我们试图精确地近似。但是,它会对原始训练集之外的任何输入产生巨大的价值。

提供数据

TensorFlow期望其数据为NumPy数组或现有张量。我正在将DataRow转换为NumPy数组:

using numpy;...const string predict = "SalePrice";ndarray GetInputs(IEnumerable<DataRow> rowSeq) {return np.array(rowSeq.Select(row => np.array(columnTypes.Where(c => c.column.ColumnName != predict).SelectMany(column => column.normalizer(row.Table.Columns.Contains(column.column.ColumnName)? (string)row[column.column.ColumnName]: "-1")).ToArray())).ToArray());
}var predictColumn = columnTypes.Single(c => c.column.ColumnName == predict);
ndarray trainOutputs = np.array(predictColumn.trainValues.AsDouble().Select(v => v ?? -1).ToArray());
ndarray trainInputs = GetInputs(trainRows);

在上面的代码中,我们将每个DataRow 转换为一个ndarray,方法是取其中的每个单元格,并应用对应于其列的ValueNormalizer。然后,我们将所有行放入另一个 ndarray,得到一个数组数组。

输出不需要这样的转换,我们只需将训练值转换为另一个ndarray.

是时候放下梯度了

有了这个设置,我们训练网络所需要做的就是调用模型的fit函数:

model.fit(trainInputs, trainOutputs,epochs: 2000,validation_split: 0.075,verbose: 2);

这个调用实际上会留出最后7.5%的训练集用于验证,然后重复以下2000次:

  1. 把剩下的trainInputs分成几批
  2. 将这些批次一一喂入神经网络
  3. 使用我们上面定义的损失函数计算误差
  4. 通过单个神经元连接的梯度反向传播误差,调整权重

在训练时,它会将网络在其留出用于验证的数据上的错误输出为val_loss,并将训练数据本身上的错误输出为loss。通常,如果val_loss变得比loss大得多,则表示网络开始过度拟合。我将在以下文章中更详细地讨论这个问题。

如果你做的一切都正确,你的一个损失的平方根应该是20000的数量级。

提交

我不会在这里谈论生成要提交的文件。计算输出的代码很简单:

const string SubmissionInputFile = "test.csv";
DataTable submissionData = LoadData(SubmissionInputFile);
var submissionRows = submissionData.Rows.Cast<DataRow>();
ndarray submissionInputs = GetInputs(submissionRows);
ndarray sumissionOutputs = model.predict(submissionInputs);

它主要使用之前定义的函数。

然后你需要将它们写入一个.csv文件,它只是一个间的的Id,predicted_value对列表。

当你提交你的结果时,你应该得到一个0.17的分数,它会在公共排行榜的最后四分之一的某个地方。但是,嘿,如果它像具有27个神经元的3层网络一样简单,那些讨厌的数据科学家就不会从美国主要公司那里获得每年30万美元以上的总薪酬。

总结

此文章的完整源代码(包含所有帮助程序,以及我早期探索和实验的一些注释掉的部分)在PasteBin上大约有200行。

在下一篇文章中,您将看到我试图进入公共排行榜前50%的恶作剧。这将是业余爱好者的冒险,使用流浪者唯一的工具与过度拟合的风车作斗争——一个更大的模型(例如,深度神经网络,记住,没有手动特征工程!)。这将不再是一个编码教程,而更多地是一个带有非常诡异的数学和一个奇怪的结论的思想探索。

敬请关注!

链接

  • Kaggle
  • Kaggle上的房价竞赛
  • TensorFlow回归教程
  • TensorFlow主页
  • TensorFlow API 参考
  • 渐变(TensorFlow 绑定)

https://www.codeproject.com/Articles/1278115/NET-TensorFlow-and-the-Windmills-of-Kaggle

.NET、TensorFlow和Kaggle的风车相关推荐

  1. 最终章 | TensorFlow战Kaggle“手写识别达成99%准确率

    刘颖,某互联网创业公司COO,技术出身,做产品里最懂运营的. 这是一个TensorFlow的系列文章,本文是第三篇,在这个系列中,你讲了解到机器学习的一些基本概念.TensorFlow的使用,并能实际 ...

  2. Tensorflow实现kaggle猫狗识别(循序渐进进行网络设计)

    这篇是tensorflow版本,pytorch版本会在下一篇博客给出 友情提示:尽量上GPU,博主CPU上跑一个VGG16花了1.5h... Tensorflow实现kaggle猫狗识别 数据集获取 ...

  3. 用TensorFlow做Kaggle“手写识别”达到98%准确率-详解

    (点击"阅读原文"即可进入查看课程表) 刘颖,某互联网创业公司COO,技术出身,做产品里最懂运营的. 这是一个TensorFlow的系列文章,本文是第三篇,在这个系列中,你讲了解到 ...

  4. 猫狗识别(tensorflow)kaggle

    1.本人安装的环境为python3.7,pacharm1.1,windows系统 详细代码见这里 2.预处理 导入train data里面的图片 异常数据清理:训练集中大约包含了一些非猫或狗的图像,这 ...

  5. 深度学习tensorflow之kaggle猫狗大战实现

    出处:http://www.fengchang.cc/post/100 今天彻底完成猫狗大战的任务,来几张图展示一下, 源代码在此​,本文图的是在模型训练到52000个batch时保存的checkpo ...

  6. 使用Opencv构建一个简单的图像相似检测器(MSE、SSIM)

    介绍 作为人类,我们通常非常善于发现图像中的差异.例如,常见的游戏--两张图像找不同.现在让我们玩下这个游戏吧,首先让我们看看上面的图像,三十秒内看看是否能够从中找出有什么不同的地方.         ...

  7. 猫狗大战使用CNN分类

    一.构造数据集 我们直接下载下来的猫狗数据集是分为训练集和测试集的25000张猫狗图像. 这个数据集太大了而且猫狗没有分类,我们需要创建一个新的数据集.分为每个类别各1000个样本的训练集和每个类别各 ...

  8. 史上最全的机器学习资料(下)

    机器学习(Machine Learning, ML)是一门多领域交叉学科,涉及概率论.统计学.逼近论.凸分析.算法复杂度理论等多门学科.专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能 ...

  9. 史上最全的机器学习资料

    摘要: 机器学习牵涉的编程语言十分之广,包括了MATLAB.Python.Clojure.Ruby等等.为了让开发者更加广泛.深入地了解机器学习,云栖社区组织翻译了GitHub Awesome Mac ...

最新文章

  1. mysql -uroot -proot tc -e select * from merchandise limit 1这个-E的命令作用是什么,用来什么什么的?
  2. python批量发送邮件_Python批量发送邮件
  3. OJ1070: 小汽车的位置(C语言)
  4. 如何使用jQuery设置输入文本的值
  5. android 主流应用,android应用推广系列(一):国内几个google主流应用市场介绍
  6. Rider编译UE5项目RD报错
  7. 美团智能配送系统的运筹优化实战
  8. 如何使用 CSS 设置 HTML 表格样式
  9. Chrome Extension ContextMenus 创建 适配Manifest3
  10. git提交失败running pre-commit hook: lint-staged [33m‼ Some of your tasks use `git add` command
  11. 联想小新 win10电脑系统安装教程
  12. 联想笔记本突然没声音了,但是音量却是打开得,F1亮着
  13. 嵌入式中SIM卡接口电路设计
  14. python-opencv创建空白图
  15. 医院绩效考核上报工作迫在眉睫,如何顺利完成?
  16. Facebook联合创始人Chris Hughes呼吁该公司进行分拆
  17. 单片机彩灯移动实验_单片机彩灯实验
  18. 雪茄星系、玫瑰星云和灵魂星云
  19. 人工神经网络教程第四版,人工神经网络教程视频
  20. IMAU OJ一招制胜

热门文章

  1. c向python注册函数_python如何调用C, 如何注册成C的回调函数(python后台程序常用方法)...
  2. 元宵节电商促销首页设计PSD分层模板
  3. 新拟物立体情人节主题图标来了,适合潮流现代的主题设计!
  4. 电商美工忙不停,年货节海报素材模板,拯救电商汪
  5. 环保公益PSD分层海报,小景合成美好世界
  6. webpack打包后的文件夹是空的_webpack打包Vue工程
  7. 图片复印如何去除黑底_如何用AE制作可爱漂亮闪烁霓虹灯效果?只需简单几步任何人都可以...
  8. C++中内联函数和宏定义的区别
  9. 2021年二月下旬文章导读与开源项目仓库 | scatter-gather DMA,SR-IOV,ARP欺骗,中断,Lockdep,virtio,vhost
  10. linux tar 命令