【问题标题】:how to build and train an lstm network in tensorflow.js如何在 tensorflow.js 中构建和训练 lstm 网络
【发布时间】:2018-09-27 23:42:22
【问题描述】:

我正在尝试使用 tensorflow.js 构建和训练一个 lstm 网络,我的数据集就像

输入:“我不喜欢这双鞋,它们对我来说太黄了。所以退回它们。” 预期输出原因:“颜色”

我可以使用预训练的 word2vec 模型将文本呈现为向量。 尝试阅读文档tensorflow.js,但我无法从中理解,即使从其他来源也找不到如何在 tensorflow.js 中实现和训练网络的好例子。

谁能提供一个使用 LSTM 层创建模型并使用 node.js 和 tensorflow.js 对其进行训练的直接示例?

【问题讨论】:

    标签: node.js lstm tensorflow.js


    【解决方案1】:

    这是一个带有多层 LSTM 的 RNN 示例,它实现了 Word2Vec。我认为您不需要对其进行太多调整以匹配您的用例 - 可能只需要数据源和超参数。当然,您也需要编写自己的测试函数。既然您说您可以提供自己的预训练 Word2Vec 向量,那么您也可以根据需要删除大部分代码。

    我应该注意 - 我写了这个例子,我的偏好是使用一个名为 Numjs 的库来创建向量(它是一个类似于 Numpy 的库),然后将它们转换为 Tensorflow.js 使用的张量。这并不是 Tensorflow.js 的设计用途,但我发现他们创建张量的方法过于繁琐且不直观。

    无论如何,这是我的示例(使用 node.js)。我希望你觉得它有用。

    require('@tensorflow/tfjs-node')
    const tf = require('@tensorflow/tfjs');
    const fs = require('fs');
    var nj = require('numjs');
    
    const maxlen = 30;
    const step = 3;
    fs.readFile(<file>, 'utf8', function (error, data) {
        if (error) throw error;
        var text = data.toString();
        create_model(text)
    });
    
    
    function onlyUnique(value, index, self) {
      return self.indexOf(value) === index;
    }
    
    function indexOfMax(arr) {
        if (arr.length === 0) {
            return -1;
        }
        var max = arr[0];
        var maxIndex = 0;
        for (var i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                maxIndex = i;
                max = arr[i];
            }
        }
        return maxIndex;
    }
    
    function sample(preds, temperature) {
      preds = nj.array(preds, 'float64');
      preds = nj.log(preds).divide(temperature)
      exp_preds = nj.exp(preds)
      preds = exp_preds.divide(nj.sum(exp_preds))
      arr = preds.tolist()
      return indexOfMax(arr)
    }
    
    async function create_model(text) {
      /* data prep */
      text = text.toLowerCase()
      console.log('corpus length:', text.length)
      var words = text.replace(/(\r\n\t|\n|\r\t)/gm," ").split(" ")
      words = words.filter(onlyUnique)
      words = words.sort()
      words = words.filter(String)
    
      console.log("total number of unique words" + words.length)
    
      var word_indices = {}
      var indices_word = {}
      for (let e0 of words.entries()) {
        var idx = e0[0]
        var word = e0[1]
        word_indices[word] = idx
        indices_word[idx] = word
      }
    
      console.log("maxlen: " + maxlen, " step: " + step)
    
      var sentences = []
      var sentences1 = []
    
      var next_words = []
      list_words = text.toLowerCase().replace(/(\r\n\t|\n|\r\t)/gm," ").split(" ").filter(String)
      console.log('list_words ' + list_words.length)
    
      for (var i = 0; i < (list_words.length - maxlen); i += step) {
        var sentences2 = list_words.slice(i, i + maxlen).join(" ")
        sentences.push(sentences2)
        next_words.push(list_words[i + maxlen])
      }
      console.log('nb sequences(length of sentences):', sentences.length)
      console.log("length of next_word", next_words.length)
    
      console.log('Vectorization...')
      var X = nj.zeros([sentences.length, maxlen, words.length])
      console.log('X shape' + X.shape)
      var y = nj.zeros([sentences.length, words.length])
      console.log('y shape' + y.shape)
      for (let e of sentences.entries()) {
        var i = e[0]
        var sentence = e[1]
        for (let e2 of sentence.split(" ").entries()) {
          var t = e2[0]
          var word = e2[1]
          X.set(i, t, word_indices[word], 1)
        }
        y.set(i, word_indices[next_words[i]], 1)
      }
    
      console.log('Creating model... Please wait.');
    
      console.log("MAXLEN " + maxlen + ", words.length " + words.length)
      var model = tf.sequential();
      model.add(tf.layers.lstm({
        units: 128,
        returnSequences: true,
        inputShape: [maxlen, words.length]
      }));
      model.add(tf.layers.dropout(0.2))
      model.add(tf.layers.lstm({
        units: 128,
        returnSequences: false
      }));
      model.add(tf.layers.dropout(0.2))
      model.add(tf.layers.dense({units: words.length, activation: 'softmax'}));
    
      model.compile({loss: 'categoricalCrossentropy', optimizer: tf.train.rmsprop(0.002)});
    
      x_tensor = tf.tensor3d(X.tolist(), null, 'bool')
      //x_tensor.print(true)
      y_tensor = tf.tensor2d(y.tolist(), null, 'bool')
      //y_tensor.print(true)
    
      /* training */
      await model.fit(x_tensor, y_tensor, {
        epochs: 100,
        batchSize: 32,
        callbacks: {
          onEpochEnd: async (epoch, logs) => {
            console.log(logs.loss + ",")
          }
        }
      })
    

    【讨论】:

    • 感谢您的回复。
    • 我仍然坚持将我的输入和输出转换为 tensor3d,我正在尝试这样 var input = tf.tensor3d(dataArray);和 dataArray = [ [长度 300],[长度 300]。 . .],给出错误:tensor3d() 要求值为 number[][][] 或 flat/TypedArray,你能指出我是否遗漏了什么。
    • 对不起,我没有时间尝试。刚刚重新开始工作。我相信 tensor2d() 应该可以工作,你能解释一下如何选择输入形状,假设我的数据集就像对象数组,每个对象都有输入段落和输出句子。但段落的长度不固定。
    • @Manoj 您需要用空值填充输入,以将输入向量向上/向下填充或剪切到预定义的大小(通常是动态确定的)。您可以使用预填充(将空值附加到开头)或后填充。我可以推荐教程,但很遗憾,它们不会用 Tensorflow.js 编写。
    • 我不确定填充或剪切向量,我的实际输入是来自客户服务电话的转录,因此电话可能长达 1 小时或几分钟。如果上面提到的那些教程是用python的,我可以尝试管理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    • 2021-09-11
    • 1970-01-01
    相关资源
    最近更新 更多