在这篇文章中,我们将使用TensorFlow.js,D3.js和网络的力量来可视化训练模型的过程,以预测棒球数据中的坏球(蓝色区域)和好球(橙色区域)。在整个训练过程中,我们将一步一步的将模型预测出的好球区域动态的展示出来。您可以通过访问Observable notebook网站在浏览器中运行此模型。

clipboard.png

体育方面的高级指标

如今的职业体育环境里充满了大量的数据。这些数据被团队、业余爱好者和粉丝应用于各种案例。感谢像TensorFlow这样的框架,使得这些数据集可以应用于机器学习领域。

美国职业棒球大联盟高级媒体(MLBAM)发布了一个可供公众研究的大型数据集。该数据集包含有关过去几年在MLB游戏中投掷的投球的传感器信息。从这个数据集中挑选了一个包含5000个样本(2,500个坏球和2,500个好球)的训练集用于此处实验。

以下是训练数据的具体数据格式示例:

clipboard.png

以下是绘制好球区域时的训练数据分布。蓝点被标记为坏球,橙点被标记为好球(标注来自大联盟裁判员)

clipboard.png

使用TensorFlow.js构建模型

TensorFlow.js将机器学习带入JavaScript和Web领域。我们将使用这个优秀的框架来构建一个深度神经网络模型。这个模型将能够以大联盟裁判的精确度来区分好球和坏球。

该模型从PITCHf/x中选出以下评测指标进行训练:

  • 协调球越过本垒的位置('px'和'pz')
  • 击球手站在球场的哪一侧
  • 击球区(击球手的躯干)的高度,以英尺为单位。
  • 击球区底部的高度(击球手的膝盖)以英尺为单位
  • 该次击球是好球还是坏球(由裁判员判定的)

结构

我们将使用TensorFlow.js的Layers API定义此模型。Layers API基于Keras,对以前使用过Keras框架的人来说应该很熟悉:

const model = tf.sequential();

// Two fully connected layers with dropout between each:
model.add(tf.layers.dense({units: 24, activation: 'relu', inputShape: [5]}));
model.add(tf.layers.dropout({rate: 0.01}));
model.add(tf.layers.dense({units: 16, activation: 'relu'}));
model.add(tf.layers.dropout({rate: 0.01}));

// Only two classes: "strike" and "ball":
model.add(tf.layers.dense({units: 2, activation: 'softmax'}));

model.compile({
  optimizer: tf.train.adam(0.01),
  loss: 'categoricalCrossentropy',
  metrics: ['accuracy']
});

加载和准备数据

精选的训练集可以在GitHub gist获取。该数据集是CSV格式的,需要下载下来在本地转换成符合TensorFlow.js的格式。

const data = [];
csvData.forEach((values) => {
  // 'logit' data uses the 5 fields:
  const x = [];
  x.push(parseFloat(values.px));
  x.push(parseFloat(values.pz));
  x.push(parseFloat(values.sz_top));
  x.push(parseFloat(values.sz_bot));
  x.push(parseFloat(values.left_handed_batter));
  // The label is simply 'is strike' or 'is ball':
  const y = parseInt(values.is_strike, 10);
  data.push({x: x, y: y});
});
// Shuffle the contents to ensure the model does not always train on the same
// sequence of pitch data:
tf.util.shuffle(data);

解析CSV数据后,需要将JS类型转换为Tensor batches才能进行训练和评估。有关此过程的详细信息,请参阅code lab。TensorFlow.js团队正在开发一种新的数据API接口,以便使数据获取在将来变得更容易。

训练模型

让我们把前期的准备都综合起来吧。定义好了模型,准备好了训练数据,现在我们将要开始训练了。以下的异步方法训练了一批训练样本并更新热图:

// Trains and reports loss+accuracy for one batch of training data:
async function trainBatch(index) {
  const history = await model.fit(batches[index].x, batches[index].y, {
    epochs: 1,
    shuffle: false,
    validationData: [batches[index].x, batches[index].y],
    batchSize: CONSTANTS.BATCH_SIZE
  });

  // Don't block the UI frame by using tf.nextFrame()
  await tf.nextFrame();
  updateHeatmap();
  await tf.nextFrame();
}

可视化模型的准确度

使用来自均匀放置在本垒板上方的 4英尺x4英尺 栅格的预测矩阵来构建热图。在每个训练步骤之后将该矩阵传递到模型中以检查模型的准确度。使用D3库将预测结果呈现为热图。

clipboard.png

建立预测矩阵

热图中所使用的预测矩阵从本垒板的中间开始,向左和向右各延伸2英尺宽,高度从本垒板的底部到4英尺高。好球区域位于本垒板上方1.5至3.5英尺之间。下图在二维平面上呈现出各个矩阵之间的关系:

将预测矩阵与模型一起使用

当每个批次的训练数据都在模型中训练之后,我们将预测矩阵传递到模型中,这样就可以去预测好球和坏球了。

function predictZone() {
  const predictions = model.predictOnBatch(predictionMatrix.data);
  const values = predictions.dataSync();

  // Sort each value so the higher prediction is the first element in the array:
  const results = [];
  let index = 0;
  for (let i = 0; i < values.length; i++) {
    let list = [];
    list.push({value: values[index++], strike: 0});
    list.push({value: values[index++], strike: 1});
    list = list.sort((a, b) => b.value - a.value);
    results.push(list);
  }
  return results;
}

使用D3生成热图

我们可以使用D3来显示预测结果。50x50尺寸的每个元素在SVG中呈现为10px x 10px的矩形。每个矩形的颜色取决于预测结果(好球或坏球)以及模型对该结果的确定程度(从50%-100%)。以下代码段显示了如何使用D3 svg 矩形组去更新数据:

function updateHeatmap() {
  rects.data(generateHeatmapData());
  rects
    .attr('x', (coord) => { return scaleX(coord.x) * CONSTANTS.HEATMAP_SIZE; })
    .attr('y', (coord) => { return scaleY(coord.y) * CONSTANTS.HEATMAP_SIZE; })
    .attr('width', CONSTANTS.HEATMAP_SIZE)
    .attr('height', CONSTANTS.HEATMAP_SIZE)
    .style('fill', (coord) => {
      if (coord.strike) {
        return strikeColorScale(coord.value);
      } else {
        return ballColorScale(coord.value);
      }
  });
}

有关使用D3绘制热图的完整详细信息,请参阅此部分

总结

如今web前端有许多令人惊叹的库和工具来创建可视化视觉效果。把这些与机器学习的强大功能和TensorFlow.js相结合,可以使开发人员创建一些非常有趣的demo。

注:本文为译文,点击此处预览原文


阳呀呀
2.2k 声望2.7k 粉丝