设置机器学习算法并使用 Java 开发您的第一个预测函数。 自动驾驶汽车、面部识别系统和语音助手都是使用机器学习技术和框架开发的。而这只是第一波。未来 10 年,新一代产品将改变我们的世界,带来程序、产品和应用开发的新方法。
作为一名 Java 程序员,您希望抓住这一浪潮,因为科技公司开始大力投资机器学习。你今天学到的东西可以在未来五年中使用。但从哪里开始呢?本文旨在回答这个问题。通过遵循我们实施和准备机器学习算法的简短指南,您将对机器学习的原理有第一印象。在了解学习算法的结构以及可用于训练它、评估它并选择提供最佳预测精度的函数之后,您将了解如何使用 JVM 框架 (Weka)构建机器学习解决方案。本文重点讨论监督机器学习,因为它是开发智能应用程序中最常用的原理。
机器学习和人工智能
机器学习从人工智能领域发展而来,旨在创造能够模仿人类智能的机器。尽管“机器学习”一词起源于计算机科学,但人工智能并不是一个新的科学领域。
图灵测试由数学家阿兰·图灵在20世纪50年代初开发,是最早设计用于确定计算机是否具有真正智能的测试之一。根据图灵测试,计算机通过模仿一个人来证明人类智能的存在,而后者没有意识到他正在与机器交谈。
当今许多流行的机器学习方法都基于几十年前的想法。但过去十年的计算(和分布式计算平台)已经为应用机器学习算法带来了足够的力量。其中大多数需要大量的矩阵乘法和其他数学计算。二十年前,进行此类计算的计算技术根本不存在,但现在它们已成为现实。机器学习算法允许程序执行质量改进过程并扩展其功能,而无需人工干预。使用机器学习开发的程序能够独立更新或扩展自己的代码。
监督学习与无监督学习
监督学习和无监督学习是两种最流行的机器学习方法。这两种选择都需要向机器提供大量数据记录来建立关系并从中学习。这种收集的数据通常称为
“特征向量”。例如,我们有一栋住宅楼。在这种情况下,特征向量可能包含诸如:房屋总面积、房间数量、房屋建造年份等特征。
在监督学习中,机器学习算法被训练来回答与特征向量相关的问题。为了训练算法,需要输入一组特征向量和相关标签。相关标签由一个人(老师)提供,它包含所提问题的正确“答案”。学习算法分析特征向量和正确的标签,以找到它们之间的内部结构和关系。这样机器就能学会正确回答问题。作为一个例子,我们可以考虑一个房地产交易的智能应用程序。它可以使用特征向量进行训练,包括一组房屋的大小、房间数量和建造年份。人们必须根据这些因素为每栋房子分配一个带有正确价格的标签。通过分析这些数据,智能应用程序应该训练自己回答这个问题:“我可以买这栋房子多少钱?”
一旦准备过程完成,新的输入数据就不再被标记。机器必须能够正确回答问题,即使对于未知的、未标记的特征向量也是如此。在无监督学习中,算法旨在无需人工标记(甚至无需提出问题)即可预测答案。无监督学习算法不是确定标签或结果,而是使用大型数据集和计算能力来发现以前未知的关系。例如,在消费品营销中,无监督学习可用于识别隐藏的关系或客户群体,这最终可以帮助改进营销计划或创建新的营销计划。在本文中,我们将重点关注监督机器学习;这是目前最常用的方法。
监督机器学习
所有的机器学习都是基于数据的。对于监督机器学习项目,您需要用标记来标记数据,以便为所提出的问题提供有意义的答案。下面的表 1 中,每条房屋信息记录都标记为“房价”。通过识别记录数据和房屋价格之间的关系,该算法最终应该能够预测未包含在给定列表中的房屋的市场价格。(请注意,房屋面积以平方米表示,房屋价格以欧元表示)。
表1. 房屋清单
|
符号 |
符号 |
符号 |
标签 |
房屋面积 |
房间的数量 |
房子的年龄 |
预计房价 |
90 平方米/295 英尺 |
2 间客房 |
23岁 |
249,000 欧元 |
101 平方米 / 331 英尺 |
3 间客房 |
不适用 |
338,000 欧元 |
1330 平方米 / 4363 英尺 |
11间客房 |
12年 |
6,500,000 欧元 |
在早期阶段,您可能会手动标记数据,但最终您将教您的程序自行完成此操作。您可能已经看到这种方法适用于电子邮件客户端,为了将电子邮件移至垃圾邮件文件夹,您需要回答“这封电子邮件是垃圾邮件吗?”的问题。当您回复时,您可以训练程序识别您不想看到的电子邮件。应用程序的垃圾邮件过滤器经过训练,可以标记来自相同来源或包含相同内容的邮件,并根据适当的规则对其进行管理。标记数据集仅用于准备和测试目的。完成此步骤后,机器学习算法将处理未标记的数据。例如,您可以向预测算法提供有关房屋的新的、未标记的数据记录,它应该根据从准备数据中获得的“知识”自动预测房屋的预期价格。
机器如何学习预测
监督机器学习的挑战是为给定问题找到合适的预测函数。从数学上来说,困难在于找到一个以变量作为输入
х
并返回预测值的函数
у
。假设的这种功能
(hθ)
是准备过程的结果。假设函数通常也称为目标函数或预测函数。
y = h θ (x)
大多数情况下,
х
它是一个数据数组。在我们的示例中,这是定义房屋的二维元素数组,由房间数量和房屋面积组成。这些值的数组就是特征向量。通过指定特定的目标函数,我们可以用它来预测每个特征向量
х
。要预测房屋的价格,必须使用由
{101.0, 3.0}
房屋面积和房间数量组成的特征向量来调用目标函数:
Function<Double[], Double> h = ...;
Double[] x = new Double[] { 101.0, 3.0 };
double y = h.apply(x);
在Example-1的源代码中,数组中的值
х
代表房屋特征的向量。目标函数返回的值
у
就是房屋的预测价格。机器学习的目标是确定在给定未知输入参数的情况下尽可能准确地工作的目标函数。在机器学习中,目标函数
(hθ)
有时称为模型。该模型是学习过程的结果。
基于标记的训练样本,学习算法在训练数据中寻找结构或模式。因此它构建了一个通常对数据有利的模型。一般来说,学习过程本质上是探索性的。在大多数情况下,使用不同的学习算法和配置变体,该过程会重复多次。因此,所有模型都会根据性能指标进行评估,并选择最好的模型。并且该模型用于计算未来未标记数据的估计值。
线性回归
要教机器“思考”,您首先需要选择要使用的学习算法。例如,线性回归。这是最简单、最流行的监督机器学习算法之一。该算法假设输入特征和结果标记之间的关系是线性的。下面的一般线性回归函数通过将特征向量的所有元素乘以参数
θ
(theta)求和来返回预测值。该参数在训练过程中用于根据训练数据调整或“调整”回归函数。
h θ (x) = θ 0 * 1 + θ 1 * x 1 + ... θ n * x n
在线性回归函数中,theta 参数和特征参数用下标编号。
(θ)
下标决定了参数和特征参数
(х)
在向量中的位置。请注意,x
0特征是常数移位项,
1
对于计算目的很重要。因此,房屋面积等重要参数的索引以 x
1开头。因此,如果为 x
1分配特征向量的第一个值(房屋面积),则 x
2将采用下一个值(房间数),依此类推。示例 2 演示了线性回归函数的 Java 实现,在数学上表示为 h
θ (x)。为简单起见,使用 进行计算
double
。在该方法中
apply()
,假设数组的第一个元素等于 1.0,并将在此函数之外设置。
示例 2:Java 中的线性回归
public class LinearRegressionFunction implements Function<Double[], Double> {
private final double[] thetaVector;
LinearRegressionFunction(double[] thetaVector) {
this.thetaVector = Arrays.copyOf(thetaVector, thetaVector.length);
}
public Double apply(Double[] featureVector) {
assert featureVector[0] == 1.0;
double prediction = 0;
for (int j = 0; j < thetaVector.length; j++) {
prediction += thetaVector[j] * featureVector[j];
}
return prediction;
}
public double[] getThetas() {
return Arrays.copyOf(thetaVector, thetaVector.length);
}
}
要创建新实例
LinearRegressionFunction
,您需要指定参数
θ
。该参数或向量用于使一般线性回归函数适应基础训练数据。程序中使用的参数
θ
将在训练过程中根据训练示例进行调整。训练后的目标函数的质量将取决于为训练准备的数据的质量。在下面的例子中我们使用
LinearRegressionFunction
基于房屋大小的价格预测来进行说明。考虑到 x
0必须是值为 1.0 的常量,因此使用两个参数 初始化目标函数
θ
,其中它们是学习过程的结果。创建新示例后,对面积为 1330 平方米的房屋的价格进行预测,如下所示:
double[] thetaVector = new double[] { 1.004579, 5.286822 };
LinearRegressionFunction targetFunction = new LinearRegressionFunction(thetaVector);
Double[] featureVector = new Double[] { 1.0, 1330.0 };
double predictedPrice = targetFunction.apply(featureVector);
在下图中,您可以看到预测目标函数的图表(蓝线)。它是通过计算房屋面积所有值的目标函数而获得的。该图表还包含用于训练的价格区域对。
现在预测图看起来相当不错。图形的坐标(位置和斜率)由向量 确定
θ { 1.004579, 5.286822 }
。但如何确定哪个
θ
向量最适合您的应用呢?如果更改第一个或第二个参数,函数是否会更适合?要确定最适合的 theta 向量,您需要一个效用函数来评估目标函数的工作效果。
待续 英文翻译。作者:Gregor Roth,JavaWorld 软件架构师。
GO TO FULL VERSION