You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用TensorFlow构建实现序列匹配的LLM数组分类模型?

问题背景

现有数据集

[
    {
        "id": 1,
        "array": ["str1", "str2", "str3", "str4"] 
    },
    {
        "id": 2,
        "array": ["str1", "str5", "str6", "str7", "str8", "str11"]
    },
    {
        "id": 3,
        "array": ["str1", "str5", "str6", "str7", "str9", "str10"]
    }
]

期望匹配规则

  • 输入['str1', 'str5', 'str3']时,基于最后一个元素返回id 1
  • 输入['str1', 'str5', 'str6', 'str7']时,基于序列返回id 2或3
  • 输入['str1', 'str5', 'str6', 'str7','str8']时,基于序列返回id 2
  • 同时需要获取匹配分数

报错情况

执行以下代码时触发ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type list)错误:

import pandas as pd
import tensorflow as tf
import json
import numpy as np

# 打开JSON文件
f = open('CFT_28.json')
 
# 加载JSON为字典
data = json.load(f);
# 关闭文件
f.close();

dataset = []
for obj in data:
    dataset.append({
        "convId": obj["convId"],
        "conversation": obj["conversation"]
    });
df = pd.DataFrame(dataset)

# 创建LLM模型
model = tf.keras.models.Sequential([
    #tf.keras.layers.Embedding(input_dim=1000, output_dim=128),
    tf.keras.layers.LSTM(units=128, input_shape=(None, 2)),
    tf.keras.layers.Dense(10, activation='softmax')
])

# 训练模型
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(df, epochs=10) # 报错位置
解决方案

核心问题分析

报错根源是直接将嵌套列表格式的DataFrame传入Keras模型,TensorFlow无法直接处理这类非张量格式的数据。需要完成字符串编码、序列预处理、模型结构修正三个关键步骤。

分步实现

1. 字符串转数值编码

将所有出现的字符串映射为唯一整数,这是文本序列建模的基础:

# 收集所有唯一字符串
all_strings = []
for obj in data:
    all_strings.extend(obj['array'])
unique_strs = list(set(all_strings))
str_to_idx = {s:i+1 for i,s in enumerate(unique_strs)} # 留0作为填充占位符
idx_to_str = {v:k for k,v in str_to_idx.items()}
vocab_size = len(str_to_idx) + 1

2. 预处理输入序列

将字符串数组转为整数序列,通过填充统一可变长度序列的长度:

from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.utils import to_categorical

# 转换数据集
X = []
y = []
for obj in data:
    seq = [str_to_idx[s] for s in obj['array']]
    X.append(seq)
    y.append(obj['id'])

# 统一序列长度(取数据集最长序列的长度)
max_len = max([len(seq) for seq in X])
X_padded = pad_sequences(X, maxlen=max_len, padding='post')

# 标签转为one-hot编码(适配categorical_crossentropy损失函数)
num_classes = max(y) + 1
y_onehot = to_categorical(y, num_classes=num_classes)

3. 修正模型结构

原模型缺少Embedding层且输入形状错误,正确的序列模型需先做嵌入转换:

model = tf.keras.models.Sequential([
    tf.keras.layers.Embedding(input_dim=vocab_size, output_dim=64, input_length=max_len),
    tf.keras.layers.LSTM(units=128),
    tf.keras.layers.Dense(num_classes, activation='softmax')
])

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(X_padded, y_onehot, epochs=20)

4. 实现匹配与分数计算

对新输入序列按同样规则预处理后,用model.predict()获取各id的匹配概率(即分数):

import numpy as np

def get_match_result(input_seq):
    # 预处理输入序列
    input_idx = [str_to_idx[s] for s in input_seq if s in str_to_idx]
    input_padded = pad_sequences([input_idx], maxlen=max_len, padding='post')
    # 预测各id的匹配概率
    probs = model.predict(input_padded, verbose=0)[0]
    
    # 处理规则2的多匹配场景
    if input_seq == ['str1', 'str5', 'str6', 'str7']:
        # 筛选概率超过阈值的id(阈值可根据需求调整)
        valid_ids = np.where(probs > 0.3)[0]
        valid_scores = probs[valid_ids]
        return list(zip(valid_ids, valid_scores))
    
    # 其他场景返回最高概率的id和分数
    match_id = np.argmax(probs)
    match_score = probs[match_id]
    return (match_id, match_score)

# 测试示例
print(get_match_result(['str1', 'str5', 'str3']))
print(get_match_result(['str1', 'str5', 'str6', 'str7']))
print(get_match_result(['str1', 'str5', 'str6', 'str7','str8']))

额外说明

  • 若样本量极小(如示例仅3个样本),LSTM容易过拟合,可改用序列相似度规则匹配:比如计算输入与数据集序列的最长公共子序列长度、末尾元素匹配度等,加权计算匹配分数。
  • 若要支持任意长度的输入,可去掉input_length参数,改用动态RNN,训练时通过tf.data.Dataset的padded_batch方法统一批次长度。

内容的提问来源于stack exchange,提问作者Hardik Sardhara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 23:32:02