如何在Python中创建n-gram特征以优化文本分类模型?
在Python中为文本分类添加n-gram特征的实现方法
1. 用scikit-learn直接生成n-gram特征
这是最便捷的实现方式,CountVectorizer和TfidfVectorizer原生支持n-gram参数,可直接生成包含unigram、bigram甚至trigram的特征矩阵。
示例1:CountVectorizer生成n-gram(词频统计)
from sklearn.feature_extraction.text import CountVectorizer # 示例语料 corpus = [ "我喜欢自然语言处理", "文本分类需要有效的特征", "n-gram能捕捉上下文信息" ] # 配置生成1-gram(单字/词)+2-gram(双字词组合) vectorizer = CountVectorizer(ngram_range=(1, 2)) X_ngram = vectorizer.fit_transform(corpus) # 查看生成的特征名称 print(vectorizer.get_feature_names_out()) # 输出示例:['n', 'n gram', '喜欢', '喜欢自然', '文本', '文本分类', ...]
示例2:TfidfVectorizer生成加权n-gram
如果需要带权重的n-gram特征(更适合多数分类场景),用TfidfVectorizer即可:
from sklearn.feature_extraction.text import TfidfVectorizer tfidf_vectorizer = TfidfVectorizer(ngram_range=(1, 2)) X_tfidf_ngram = tfidf_vectorizer.fit_transform(corpus)
参数说明:ngram_range=(a,b)表示生成从a个词到b个词的所有连续组合,比如(2,3)仅生成bigram和trigram。
2. 合并n-gram特征与已有特征
若你已提取了向量化/统计特征,可通过以下方式将n-gram特征与现有特征拼接:
方式1:直接用scipy稀疏矩阵拼接
from scipy.sparse import hstack # 假设X_existing是你已提取的统计特征(如词长、标点数量等,形状为(n_samples, n_features)) # X_ngram是上面生成的n-gram特征矩阵(稀疏矩阵) X_combined = hstack([X_existing, X_ngram])
方式2:用Pipeline+FeatureUnion构建标准化流程
适合工程化场景,可整合所有特征提取步骤:
from sklearn.pipeline import Pipeline, FeatureUnion from sklearn.base import BaseEstimator, TransformerMixin from sklearn.linear_model import LogisticRegression # 自定义统计特征提取转换器 class StatisticalFeatures(BaseEstimator, TransformerMixin): def fit(self, X, y=None): return self def transform(self, X): # 这里实现你的统计特征逻辑,比如词数、字符数等 features = [] for text in X: word_count = len(text.split()) char_count = len(text) features.append([word_count, char_count]) return features # 组合特征提取模块 feature_union = FeatureUnion([ ('statistical', StatisticalFeatures()), ('ngram_tfidf', TfidfVectorizer(ngram_range=(1, 2))) ]) # 构建完整分类管道 pipeline = Pipeline([ ('features', feature_union), ('classifier', LogisticRegression()) # 替换为你使用的分类器 ]) # 训练模型(y_labels为分类标签) # pipeline.fit(corpus, y_labels)
3. 自定义n-gram提取(灵活场景)
如果需要更精细化的控制(比如只提取特定词性的n-gram、自定义分词规则),可以手动实现n-gram生成:
import jieba def generate_ngrams(text, n): # 中文先分词(可替换为其他分词工具) tokens = jieba.lcut(text) # 生成连续n个词的组合 ngrams = [] for i in range(len(tokens) - n + 1): ngram = ' '.join(tokens[i:i+n]) ngrams.append(ngram) return ngrams # 测试 text = "我喜欢自然语言处理" print(generate_ngrams(text, 2)) # 输出:['我 喜欢', '喜欢 自然', '自然 语言', '语言 处理']
生成自定义n-gram后,可通过CountVectorizer指定词汇表来转换为特征矩阵,或用Counter统计后构建特征。
关键注意事项
- 控制n的范围:n过大会导致特征维度爆炸,增加过拟合风险,通常
(1,2)或(1,3)是中文场景的常用选择。 - 特征筛选:生成n-gram后,可使用
SelectKBest等工具筛选重要特征,降低维度。 - 中文分词:务必先完成分词再生成n-gram,避免将连续汉字误判为n-gram。
内容的提问来源于stack exchange,提问作者Zen
相关产品推荐
相关产品推荐

