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

能否在神经网络中使用不同长度的输入文本数据?

处理机器学习中变长文本的编码问题

当然可以处理不同长度的文本向量啦!你现在的代码之所以只能适配固定长度文本,核心原因是用了固定输入维度的全连接层(input_dim=11),而且编码逻辑直接把字符转成索引后就喂入模型,没有处理变长序列的机制。下面给你几个实用的解决方案,从简单到进阶都有:

方案1:填充/截断(Padding/Truncation)

这是最直接的适配方法,把所有文本统一到一个固定长度:

  • 先统计所有文本的长度,选一个合适的最大长度(比如最长文本的长度,或者取数据中95%文本都不超过的长度)
  • 短文本在末尾填充特殊标记(比如0,要确保这个标记不在你的字符字典里)
  • 长文本直接截断到最大长度

修改后的代码示例:

import pandas as pd
import csv
import numpy as np
from keras.models import Sequential
from keras.layers import Dense

# 读取数据
train_set = pd.read_csv("train3.tsv", sep="\t", header=None, names=['score', 'text'], 
                        skip_blank_lines=False, quoting=csv.QUOTE_NONE, error_bad_lines=False)
test_set = pd.read_csv("test.tsv", sep="\t", header=None, names=['text'], 
                       skip_blank_lines=False, quoting=csv.QUOTE_NONE, error_bad_lines=False)

# 构建字符字典(仅用训练集字符,避免测试集引入新索引)
dictionary = {}
i = 1  # 留0作为填充标记
for text in train_set.text.str.lower():
    for char in list(text):
        if char not in dictionary:
            dictionary[char] = i
            i += 1
pad_token = 0

# 确定最大长度
max_len = max([len(text) for text in train_set.text] + [len(text) for text in test_set.text])

# 编码并填充/截断训练集
train_encoded = []
for text in train_set.text.str.lower():
    encoded = [dictionary[char] for char in list(text)]
    # 填充或截断到固定长度
    if len(encoded) < max_len:
        encoded += [pad_token] * (max_len - len(encoded))
    else:
        encoded = encoded[:max_len]
    train_encoded.append(encoded)

# 处理测试集(未知字符用填充标记代替)
test_encoded = []
for text in test_set.text.str.lower():
    encoded = [dictionary.get(char, pad_token) for char in list(text)]
    if len(encoded) < max_len:
        encoded += [pad_token] * (max_len - len(encoded))
    else:
        encoded = encoded[:max_len]
    test_encoded.append(encoded)

# 准备模型输入数据
score = np.array(train_set.score.values)
text = np.array(train_encoded)
test = np.array(test_encoded)

# 创建模型(input_dim改为max_len)
model = Sequential()
model.add(Dense(12, input_dim=max_len, init='uniform'))
model.add(Dense(11, init='uniform'))
model.add(Dense(1, init='uniform', activation='sigmoid'))  # 二分类必须加sigmoid激活

# 编译并训练
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(text, score, epochs=150, batch_size=10, verbose=2)

# 预测
predictions = model.predict(test)
print(predictions)

方案2:使用循环神经网络(LSTM/GRU)

循环神经网络天生适合处理变长序列,能捕捉字符的顺序信息,效果通常比全连接层更好。搭配Embedding层可以把字符索引转成稠密向量:

import pandas as pd
import csv
import numpy as np
from keras.models import Sequential
from keras.layers import Embedding, LSTM, Dense
from keras.preprocessing.sequence import pad_sequences

# 读取数据、构建字典步骤和方案1一致,此处省略重复代码...

# 编码保留原长度
train_encoded = [[dictionary[char] for char in list(text.lower())] for text in train_set.text]
test_encoded = [[dictionary.get(char, pad_token) for char in list(text.lower())] for text in test_set.text]

# 统一序列长度(LSTM仍需固定输入长度,但内部会处理变长逻辑)
max_len = max([len(seq) for seq in train_encoded + test_encoded])
train_padded = pad_sequences(train_encoded, maxlen=max_len, padding='post', truncating='post')
test_padded = pad_sequences(test_encoded, maxlen=max_len, padding='post', truncating='post')

# 创建序列模型
model = Sequential()
# Embedding层:输入维度是字典大小,输出维度是嵌入向量长度,输入长度是max_len
model.add(Embedding(input_dim=len(dictionary)+1, output_dim=32, input_length=max_len))
model.add(LSTM(64))  # LSTM隐藏单元数
model.add(Dense(1, activation='sigmoid'))

# 编译训练
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.fit(train_padded, score, epochs=50, batch_size=10, verbose=2)

predictions = model.predict(test_padded)
print(predictions)

方案3:字符级Bag of Characters

如果不想用神经网络,也可以用传统特征工程方法,把每个文本转成字符频率向量,不管文本多长,输出维度都是字符字典的大小:

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegression

# 读取数据步骤省略...

# 用CountVectorizer统计字符频率
vectorizer = CountVectorizer(analyzer='char')
train_features = vectorizer.fit_transform(train_set.text)
test_features = vectorizer.transform(test_set.text)

# 训练逻辑回归模型
model = LogisticRegression()
model.fit(train_features, train_set.score)
predictions = model.predict_proba(test_features)[:, 1]
print(predictions)

关键注意事项

  • 绝对不要在测试集里给新字符分配新索引!这会导致训练和测试的字典不一致,模型完全无法正确预测。测试集的未知字符应该用统一标记代替。
  • 二分类任务的输出层一定要加activation='sigmoid',否则输出范围不符合损失函数的要求。
  • 如果文本长度差异很大,优先选LSTM这类序列模型,它能更好地利用字符的顺序信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:31:32