NodeJS 如何在tensorflow.js中使用带有Python训练的自定义层的情感分析模型?

kmbjn2e3  于 2023-06-29  发布在  Node.js
关注(0)|答案(1)|浏览(83)

我是ML的新手,我想使用discord.js和tensorflow keras对Discord消息进行一些情感分析。我开始使用Python是因为我只知道Python tensorflow,但现在我遇到了无法将模型转换为tensorflow.js模型的问题。我认为这是因为tensorflow.js无法加载自定义层,比如Python tf.keras.layers.TextVectorization()

我的训练数据csv样本:

text,sentiment
"piss shit",1
"What a fu#cking airhead this is! This world really is fucked",0
"suck off",0
"I love you so much",1

我的Python模型:

vectorize_layer = tf.keras.layers.TextVectorization(
    output_mode="tf_idf"
)
vectorize_layer.adapt(train_x)

model = tf.keras.Sequential()
model.add(vectorize_layer)
model.add(tf.keras.layers.Dense(64, activation="relu"))
model.add(tf.keras.layers.Dropout(0.2))
model.add(tf.keras.layers.Dense(128, activation="relu"))
model.add(tf.keras.layers.Dropout(0.2))
model.add(tf.keras.layers.Dense(64, activation="relu"))
model.add(tf.keras.layers.Dropout(0.2))
model.add(tf.keras.layers.Dense(1, activation="sigmoid", dtype="float64"))

我无法将模型保存为TFJS模型,因为它使用了text_vectorization层。
我试着对数据进行预处理,然后将其用于训练。

我写了下面的函数来实现:

def __pad_sequence(self, sequences):
    padded_sequences = []
    for seq in sequences:
        if len(seq) > self.metadata["max_len"]:
            seq = seq[-self.metadata["max_len"]:]
        elif len(seq) < self.metadata["max_len"]:
            pad = [0] * (self.metadata["max_len"] - len(seq))
            seq = pad + seq
        padded_sequences.append(seq)
    return padded_sequences

def run(self, data):
    trimmed = re.sub(r"(\.|\,|\!)", "", data.lower()).split(" ")
    sequence = [self.metadata["word_index"]
                .get(_, 2) + self.metadata["index_from"] for _ in trimmed]
    padded_sequence = self.__pad_sequence(self, [sequence])
    input_data = tf.constant(padded_sequence,
                                shape=[1, self.metadata["max_len"]]
                                )

    return input_data

我的Node.js预处理函数:

function padSequences(sequences, metadata) {
    return sequences.map(seq => {
        if (seq.length > metadata.max_len) {
            seq.splice(0, seq.length - metadata.max_len);
        }
        if (seq.length < metadata.max_len) {
            const pad = [];
            for (let i = 0; i < metadata.max_len - seq.length; ++i) {
                pad.push(0);
            }
            seq = pad.concat(seq);
        }
        return seq;
    });
}

function prepareData(data, metadata) {
    const trimmed = data
        .trim().toLowerCase().replace(/(\.|\,|\!)/g, '').split(' ');
    const sequence = trimmed.map(word => {
        const wordIndex = metadata.word_index[word];
        if (typeof wordIndex === 'undefined') {
            return 2;
        }
        return wordIndex + metadata.index_from;
    });
    const paddedSequence = padSequences([sequence], metadata);

    const input = tf.tensor2d(paddedSequence, [1, metadata.max_len]);

    return input;
    //return paddedSequence;
}

元数据用途:[storage.googleapis.com](https://storage.googleapis.com/tfjs-models/tfjs/sentiment_cnn_v1/metadata.json

我的计划是在Node.js中预处理discord.js消息,然后将它们用于在预处理数据上训练的模型。当我尝试用预处理的数据训练模型时,我得到的准确率非常低,大约为51%,而Python中的text_vectorization则超过了90%。

这是我预处理后的数据:

# "piss shit" looks like this...
[     0     0     0     0     0     0     0     0     0     0     0     0
      0     0     0     0     0     0     0     0     0     0     0     0
      0     0     0     0     0     0     0     0     0     0     0     0
      0     0     0     0     0     0     0     0     0     0     0     0
      0     0     0     0     0     0     0     0     0     0     0     0
      0     0     0     0     0     0     0     0     0     0     0     0
      0     0     0     0     0     0     0     0     0     0     0     0
      0     0     0     0     0     0     0     0     0     0     0     0
      0     0 76508 24635]

如何在tensorflow.js中像Python tf.keras.layers.TextVectorisation()一样预处理数据,并获得与Python相同的结果?
tensorflow.js中似乎没有tf.keras.layers.TextVectorisation()

wztqucjr

wztqucjr1#

我认为TensorFlow.js不支持像TextVectorization这样的自定义层,所以你必须在Node.js应用程序中手动预处理数据,然后才能将其提供给模型。也许这会帮助你:

//Load the metadata from URL
const metadataUrl = 'https://storage.googleapis.com/tfjs-models/tfjs/sentiment_cnn_v1/metadata.json';
const metadata = await fetch(metadataUrl).then((response) => response.json());

//Preprocess the text messages
const sequence = trimmed.map((word) => {
  const index = metadata['word_index'][word];
  return index !== undefined ? index + metadata['index_from'] : 2; // 2 represents the out-of-vocabulary (OOV) token
});

const paddedSequence = sequence.slice(-metadata['max_len']).concat(Array.from({ length: metadata['max_len'] - sequence.length }).fill(0));

const inputTensor = tf.tensor2d([paddedSequence], [1, metadata['max_len']]);

编辑

您可以使用natural包,它提供了各种NLP功能,可以在Node.js中创建一个函数,该函数执行类似于tf.keras.layers.TextVectorization()的文本矢量化,但在Python TensorFlow库中。

const natural = require('natural');

function textVectorization(texts) {
  const vectorizer = new natural.TfidfVectorizer();
  const vectors = vectorizer.fit_transform(texts);

  return vectors.to2DArray();
}

// Example usage
const texts = [
  'This is the first document.',
  'This document is the second document.',
  'And this is the third one.',
  'Is this the first document?'
];

const vectorizedTexts = textVectorization(texts);
console.log(vectorizedTexts);

我没有测试这个,但它使用natural包中的TfidfVectorizer来执行矢量化。该函数首先初始化矢量化器,然后使用fit_transform方法将矢量化器拟合到输入文本,最后使用to2DArray方法将结果矢量转换为2D数组。

相关问题