将机器学习预测链接回原始数据集

时间:2015-08-07 03:57:29

标签: scala apache-spark

我正在使用少量机器学习算法对零售交易数据进行POC,并提出缺货分析的预测模型。我的问题可能听起来很愚蠢,但如果你或其他任何人能回答我,我真的很感激。

到目前为止,我已经能够获得数据集==>将要素转换为(标签点,要素向量)==>训练ML模型==>在Test DataSet上运行模型并且==>得到预测。

问题1:

由于我没有任何JAVA / Python / Scala语言的经验,我正在数据库中构建我的功能,并将该数据保存为我的机器学习算法的CSV文件。

我们如何使用原始数据中的Scala创建功能。

问题2:

源数据集包含一组(存储,产品,日期)及其记录的OOS事件(目标)的许多功能

StoreID(文本列),ProductID(文本列),TranDate,(标签/目标),Feature1,Feature2 ........................ FeatureN

由于Features只能包含数值,所以我只是从数字列而不是文本列创建功能(这对我来说是自然的键)。当我在验证集上运行模型时,我得到一个(预测,标签)数组。

现在,如何将此结果集链接回原始数据集,并查看哪个特定(商店,产品,日期)可能存在缺货事件?

我希望问题陈述足够清楚。

MJ

1 个答案:

答案 0 :(得分:3)

Spark的线性回归示例

这是Spark Docs Linear Regression example的一个片段,它非常有启发性且易于理解。

它解决了你的问题1"和"问题2"

它不需要加入,甚至不依赖于RDD订单。

// Load and parse the data
val data = sc.textFile("data/mllib/ridge-data/lpsa.data")

此处data是文本行的RDD

val parsedData = data.map { line =>
  val parts = line.split(',')
  LabeledPoint(parts(0).toDouble, Vectors.dense(parts(1).split(' ').map(_.toDouble)))
}.cache()

问题1:解析功能

这取决于数据。在这里,我们看到行正在,分割成字段。看来这个数据是完全数字数据的CSV。

第一个字段被视为标记点(因变量)的标签,其余字段从文本转换为双(浮点)并卡在矢量中。此向量包含要素或自变量。

在您自己的项目中,您需要记住的部分是解析为LabeledPoints的RDD的目标,其中LabeledPoint的第一个参数(标签)是真正的依赖数值和特征,或第二个参数,是一个数字向量。

将数据置于此状态需要知道如何编码。 Python可能最容易进行数据解析。您始终可以使用其他工具创建纯数字CSV,第一列中包含因变量,其他列中包含数字要素,没有标题行 - 然后复制示例解析函数。

// Building the model
val numIterations = 100
val model = LinearRegressionWithSGD.train(parsedData, numIterations)

此时我们有一个训练有素的model对象。 model对象具有predict method,它对特征向量进行操作并返回因变量的估计值。

编码文字功能

ML例程通常需要数字特征向量,但您通常可以将自由文本或分类特征(颜色,大小,品牌名称)转换为某些空间中的数字向量。有多种方法可以做到这一点,例如用于文本的Bag-Of-Words,或者用于分类数据的One Hot Encoding,其中您为每个可能的类别编写1.0或0.0的成员资格(但要注意多重共线性)。这些方法可以创建大的特征向量,这就是Spark为训练模型提供迭代方法的原因。 Spark还有一个SparseVector()类,您可以轻松创建除了某些特征尺寸设置为0.0以外的所有矢量

问题2:将模型预测与真值进行比较

接下来,他们使用训练数据测试此模型,但是调用 如果测试数据是LabeledPoint的RDD(依赖值,Vector(特征)),则与外部测试数据相同。可以通过将变量parsedData更改为其他RDD来更改输入。

// Evaluate model on training examples and compute training error
val valuesAndPreds = parsedData.map { point =>
  val prediction = model.predict(point.features)
  (point.label, prediction)
}

请注意,这将返回先前存储在point.label中的真因变量的元组,以及每行或LabeledPoint的point.features的模型预测。

现在我们已准备好做均值平方误差,因为valuesAndPreds RDD包含真值(v,p)的元组v和类型为Double的预测p

MSE是单个数字,首先将元组分别映射到平方距离||v-p||**2的rdd,然后取平均值,得到一个数字。

val MSE = valuesAndPreds.map{case(v, p) => math.pow((v - p), 2)}.mean()

println("training Mean Squared Error = " + MSE)

Spark的后勤示例

这是类似的,但在这里你可以看到数据已经被解析并分成训练和测试集。

// Split data into training (60%) and test (40%).
val splits = data.randomSplit(Array(0.6, 0.4), seed = 11L)
val training = splits(0).cache()
val test = splits(1)

此处模型针对训练集进行训练。

// Run training algorithm to build the model
val model = new LogisticRegressionWithLBFGS()
  .setNumClasses(10)
  .run(training)

与测试集进行测试(比较)。请注意,即使这是一个不同的模型(Logistic而不是Linear),仍然有model.predict方法将点features向量作为参数并返回该点的预测。

预测再次与标签中的真值配对,在元组中用于性能指标的比较。

// Compute raw scores on the test set.
val predictionAndLabels = test.map { case LabeledPoint(label, features) =>
  val prediction = model.predict(features)
  (prediction, label)
}

// Get evaluation metrics.
val metrics = new MulticlassMetrics(predictionAndLabels)
val precision = metrics.precision
println("Precision = " + precision)

加入怎么样?因此,如果您有两个(键,值)对的RDD,则需要RDD.join,并且需要一个与两个值的交叉点对应的RDD。但我们在这里并不需要。