Text_Classification

GitHub
1.8k 543 简单 2 次阅读 1周前MIT语言模型开发框架
AI 解读 由 AI 自动生成,仅供参考

Text_Classification 是一份专注于文本分类算法的开源综述资源,旨在为用户提供从数据预处理到模型构建的全流程指导。它主要解决自然语言处理中原始文本噪声大、特征难以提取的问题,例如停用词干扰、拼写错误或格式混乱,这些都会显著影响分类效果。通过系统讲解文本清洗、分词、大小写标准化及特征提取(如词嵌入和加权词)等方法,Text_Classification 为构建高效分类器提供了清晰的技术路径。

这份资源非常适合 NLP 领域的研究人员、算法工程师以及正在学习机器学习的学生。它不仅包含理论概述,还附带了基于 NLTK 等库的 Python 代码示例,涵盖分词实现和停用词过滤等实际操作。对于需要快速搭建文本分析 pipeline 或深入理解分类算法原理的用户来说,Text_Classification 是一个兼具实用性与学术价值的参考宝库,能帮助团队减少重复造轮子的时间,专注于核心业务逻辑的实现。

使用场景

某电商平台客服团队每日需处理上万条用户评论,旨在快速识别问题类型以优化服务体验。

没有 Text_Classification 时

  • 人工逐条阅读评论,效率低下且极易因疲劳导致误判,响应速度慢
  • 原始文本包含大量网络缩写和拼写错误,直接干扰关键词匹配效果
  • 缺乏标准化的分词与去噪流程,导致特征提取不准确,模型泛化能力差
  • 历史数据堆积无法结构化,难以挖掘潜在的产品改进方向,决策滞后

使用 Text_Classification 后

  • 利用其内置的分词与停用词过滤功能,自动清理文本中的无效噪声,提升数据质量
  • 基于算法自动将评论精准归类为“产品质量”、“物流配送”或“售后服务”,准确率高
  • 标准化特征提取确保了不同来源数据的分类逻辑高度一致,便于后续分析
  • 批量处理能力使原本需数周的人工标注工作缩短至几小时内完成,释放人力

通过集成文本清洗与分类算法,实现了从非结构化数据到可执行洞察的高效转化。

运行环境要求

操作系统
  • Linux
  • macOS
GPU

未说明

内存

未说明

依赖
notes本项目为文本分类算法综述仓库,整合了多种特征提取与模型实现(如 Word2Vec, GloVe, ELMo)。代码示例依赖 NLTK 和 autocorrect 库。Word2Vec 组件包含针对 Mac OS X 的编译补丁。运行演示脚本需联网下载约 100MB 训练语料。
python未说明
nltk
autocorrect
Text_Classification hero image

快速开始

################################################ 文本分类算法:综述 ################################################

|UniversityCube| |DOI| |Best| |medium| |mendeley| |contributions-welcome| |arXiv| |ansicolortags| |contributors| |twitter|

.. figure:: docs/pic/WordArt.png

引用论文 : 文本分类算法:综述 <https://arxiv.org/abs/1904.08067>__

|BPW|

################## 目录 ################## .. contents:: :local: :depth: 4

============ 简介

.. figure:: docs/pic/OverviewTextClassification.png

==================================== 文本与文档特征提取


对于分类算法而言,文本特征提取和预处理非常重要。在本节中,我们开始讨论文本清洗,因为大多数文档包含大量噪声。在这一部分,我们讨论两种主要的文本特征提取方法——词嵌入(word embedding)和加权词(weighted word)。

文本清洗与预处理

在自然语言处理(Natural Language Processing, NLP)中,大多数文本和文档包含许多对文本分类冗余的词汇,例如停用词(stopwords)、拼写错误、俚语等。在本节中,我们将简要解释一些用于文本清洗和预处理文本文档的技术和方法。在许多算法中,如统计和概率学习方法,噪声和不必要的特征会对整体性能产生负面影响。因此,消除这些特征极其重要。


分词

分词(Tokenization)是将文本流分解为单词、短语、符号或任何其他称为 token 的有意义元素的过程。这一步的主要目标是提取句子中的单个单词。除了文本分类外,在文本挖掘中,有必要在管道(pipeline)中集成一个解析器(parser)来执行文档的分词;例如:

句子:

.. code::

After sleeping for four hours, he decided to sleep for another four

在这种情况下,tokens 如下所示:

.. code::

{'After', 'sleeping', 'for', 'four', 'hours', 'he', 'decided', 'to', 'sleep', 'for', 'another', 'four'}

以下是 Python 代码用于分词:

.. code:: python

from nltk.tokenize import word_tokenize text = "After sleeping for four hours, he decided to sleep for another four" tokens = word_tokenize(text) print(tokens)


停用词

社交媒体上的文本和文档分类,如 Twitter、Facebook 等,通常受到文本语料库噪声性质(缩写、不规则形式)的影响。

这是来自 geeksforgeeks <https://www.geeksforgeeks.org/removing-stop-words-nltk-python/>__ 的一个示例。

.. code:: python

from nltk.corpus import stopwords from nltk.tokenize import word_tokenize

example_sent = "This is a sample sentence, showing off the stop words filtration."

stop_words = set(stopwords.words('english'))

word_tokens = word_tokenize(example_sent)

filtered_sentence = [w for w in word_tokens if not w in stop_words]

filtered_sentence = []

for w in word_tokens: if w not in stop_words: filtered_sentence.append(w)

print(word_tokens) print(filtered_sentence)

输出:

.. code:: python

['This', 'is', 'a', 'sample', 'sentence', ',', 'showing', 'off', 'the', 'stop', 'words', 'filtration', '.'] ['This', 'sample', 'sentence', ',', 'showing', 'stop', 'words', 'filtration', '.']


大小写转换

句子可以包含大写字母和小写字母的混合。多个句子组成一个文本文档。为了减少问题空间,最常见的方法是将所有内容转换为小写。这将文档中的所有单词置于同一空间中,但通常会改变某些单词的含义,例如将 "US" 变为 "us",前者代表美利坚合众国,后者是代词。为了解决这个问题,可以应用俚语和缩写转换器。

.. code:: python

text = "The United States of America (USA) or America, is a federal republic composed of 50 states" print(text) print(text.lower())

输出:

.. code:: python

"The United States of America (USA) or America, is a federal republic composed of 50 states" "the united states of america (usa) or america, is a federal republic composed of 50 states"


俚语与缩写

俚语和缩写在执行预处理步骤时可能会导致问题。缩写是单词的缩短形式,例如 SVM 代表支持向量机(Support Vector Machine)。俚语是一种描绘非正式对话或具有不同含义文本的语言版本,例如 "lost the plot",它本质上意味着“他们疯了”。处理这些词的常见方法是将其转换为正式语言。


噪声去除

作为预处理步骤的文本清洗的另一个问题是噪声去除。文本文档通常包含标点符号或特殊字符等字符,它们对于文本挖掘或分类目的来说不是必需的。虽然标点符号对于理解句子的含义至关重要,但它可能会负面地影响分类算法。

以下是从文本中删除标准噪声的简单代码:

.. code:: python

def text_cleaner(text): rules = [ {r'>\s+': u'>'}, # remove spaces after a tag opens or closes {r'\s+': u' '}, # replace consecutive spaces {r'\s*<br\s*/?>\s*': u'\n'}, # newline after a
{r'</(div)\s*>\s*': u'\n'}, # newline after

and
and

... {r'</(p|h\d)\s*>\s*': u'\n\n'}, # newline after

and

and

... {r'.<\s*(/head|body)[^>]>': u''}, # remove to {r'<a\s+href="([^"]+)"[^>]>.': r'\1'}, # show links instead of texts {r'[ \t]*<[^<]*?/?>': u''}, # remove remaining tags {r'^\s+': u''} # remove spaces at the beginning ] for rule in rules: for (k, v) in rule.items(): regex = re.compile(k) text = regex.sub(v, text) text = text.rstrip() return text.lower()


拼写纠正

预处理步骤的一个可选部分是纠正拼写错误的单词。不同的技术已被引入来解决这个问题,例如基于哈希和上下文敏感的拼写纠正技术,或使用 Trie(字典树)和 Damerau-Levenshtein 距离二元组(bigram)的拼写纠正。

.. code:: python

from autocorrect import spell

print spell('caaaar') print spell(u'mussage') print spell(u'survice') print spell(u'hte')

结果:

.. code::

caesar message service the


词干提取 (Stemming)

文本词干提取 (Text Stemming) 是通过不同的语言过程(如附加法,即词缀的添加)修改单词以获得其变体的过程。例如,单词"studying"的词干是"study",后面加上-ing。

这是来自 NLTK <https://pythonprogramming.net/stemming-nltk-tutorial/>__ 的一个词干提取示例。

.. code:: python

from nltk.stem import PorterStemmer
from nltk.tokenize import sent_tokenize, word_tokenize

ps = PorterStemmer()

example_words = ["python","pythoner","pythoning","pythoned","pythonly"]

for w in example_words:
print(ps.stem(w))

结果:

.. code::

python python python python pythonli


词形还原 (Lemmatization)

文本词形还原 (Text lemmatization) 是消除单词的冗余前缀或后缀并提取基础词(lemma)的过程。

.. code:: python

from nltk.stem import WordNetLemmatizer

lemmatizer = WordNetLemmatizer()

print(lemmatizer.lemmatize("cats"))

词嵌入 (Word Embedding)

不同的词嵌入 (Word Embedding) 过程已被提出,用于将这些一元词转换为机器学习算法可消费的输入。执行此类嵌入的一种非常简单的方法是词频~(TF),其中每个单词将被映射到一个数字,对应于该单词在整个语料库中出现的次数。其他词频函数也被使用,将词频表示为布尔值或对数缩放数字。在这里,每个文档将被转换为包含该文档中单词频率的相同长度的向量。虽然这种方法可能看起来很直观,但它存在一个问题,即语言文献中使用非常频繁的特定单词可能会主导这种词表示。

.. image:: docs/pic/CBOW.png


Word2Vec

原始来源 https://code.google.com/p/word2vec/

我已将其复制到一个 GitHub 项目中,以便我可以应用和跟踪社区补丁(包括支持 Mac OS X 编译的功能)。

compute-accuracy 实用程序中似乎存在段错误 (segfault)。

开始操作:

::

cd scripts && ./demo-word.sh

以下是原始 README 文本:

此工具提供了用于计算词向量表示的连续词袋模型 (Continuous Bag-of-Words) 和跳字模型 (Skip-gram) 架构的高效实现。这些表示随后可以用于许多自然语言处理应用程序以及进一步的研究目的。

此代码提供了连续词袋模型 (CBOW) 和跳字模型 (SG) 的实现,以及几个演示脚本。

给定一个文本语料库,word2vec 工具使用连续词袋模型或跳字模型神经网络架构为词汇表中的每个单词学习一个向量。用户应指定以下内容:所需的向量维度(跳字模型或连续词袋模型的上下文窗口大小),训练算法(层次 Softmax 和/或负采样),对频繁词进行下采样的阈值,使用的线程数,输出词向量文件的格式(文本或二进制)。

通常,其他超参数(如学习率)不需要针对不同训练集进行调整。

脚本 demo-word.sh 从网络下载一个小型(100MB)文本语料库,并训练一个小型词向量模型。训练完成后,用户可以交互式地探索单词的相似度。

有关脚本的更多信息请参见 https://code.google.com/p/word2vec/


词的全局向量表示 (Global Vectors for Word Representation / GloVe)

.. image:: /docs/pic/Glove.PNG

提供了 GloVe 模型的学习词表示的实现,并描述了如何下载网络数据集向量或自行训练。有关 GloVe 向量的更多信息,请参阅 项目页面 <http://nlp.stanford.edu/projects/glove/>__ 或 论文 <http://nlp.stanford.edu/pubs/glove.pdf>__。


上下文词表示 (Contextualized Word Representations)

ELMo 是一种深度上下文词表示,它建模了 (1) 单词使用的复杂特征(例如句法和语义),以及 (2) 这些用法如何在不同语言环境中变化(即建模多义性)。这些词向量是深度双向语言模型 (biLM) 内部状态的学习函数,该模型已在大型文本语料库上预训练。它们可以轻松添加到现有模型中,并在广泛的具有挑战性的自然语言处理问题(包括问答、文本蕴含和情感分析)中显著提高技术水平。

ELMo 表示具有以下特点:

  • 上下文相关: 每个单词的表示取决于其使用的整个上下文。
  • 深度: 词表示结合了深度预训练神经网络的所有层。
  • 基于字符: ELMo 表示完全基于字符,允许网络利用形态学线索为训练时未见过的未登录词 (out-of-vocabulary tokens) 形成鲁棒的表示。

Tensorflow 实现

用于从 "Deep contextualized word representations" <http://arxiv.org/abs/1802.05365>__ 计算 ELMo 表示的预训练 biLM 的 Tensorflow 实现。

此存储库支持训练 biLM 和使用预训练模型进行预测。

我们还在 AllenNLP <http://allennlp.org/>__ 中提供了 PyTorch 实现版本。

如果您只想进行预测,使用 Tensorflow Hub <https://www.tensorflow.org/hub/modules/google/elmo/2>__ 提供的版本可能会更容易。

预训练模型:

我们有几个可用的预训练英语语言 biLM 模型供使用。每个模型由两个单独的文件指定,一个是包含超参数的 JSON 格式“选项”文件,另一个是包含模型权重的 hdf5 格式文件。预训练模型的链接可在 此处 <https://allennlp.org/elmo>__ 找到。

根据您的用例,有三种方式将 ELMo 表示集成到下游任务中。

  1. 使用字符输入即时从原始文本计算表示。这是最通用的方法,能够处理任何输入文本。但其计算成本最高。
  2. 预计算并缓存与上下文无关的 token 表示,随后使用 biLSTMs(双向长短期记忆网络)为输入数据计算上下文相关的表示。此方法的计算成本低于 #1,但仅适用于固定且指定的词汇表。
  3. 预计算整个数据集的表示并保存至文件。

我们过去在各种用例中都使用了所有这些方法。#1 对于在测试阶段评估未见过的数据是必要的(例如公共 SQuAD leaderboard)。#2 对于大型数据集是一个很好的折衷方案,此时文件大小不可行(SNLI, SQuAD)。#3 对于较小的数据集,或者您希望在其他框架中使用 ELMo(语言模型嵌入)的情况,是一个不错的选择。

在所有情况下,流程大致遵循相同的步骤。首先,创建一个 Batcher(对于 #2 使用 TokenBatcher)将分词后的字符串转换为字符(或 token)id 的 numpy 数组。然后,加载预训练的 ELMo 模型(类 BidirectionalLanguageModel)。最后,对于步骤 #1 和 #2,使用 weight_layers 计算最终的 ELMo 表示。对于 #3,使用 BidirectionalLanguageModel 将所有中间层写入文件。

.. figure:: docs/pic/ngram_cnn_highway_1.png 应用于示例句子的语言模型架构 [参考:arXiv paper <https://arxiv.org/pdf/1508.06615.pdf>__].

.. figure:: docs/pic/Glove_VS_DCWE.png


FastText

.. figure:: docs/pic/fasttext-logo-color-web.png

fastText 是一个用于高效学习单词表示和句子分类的库。

Github: facebookresearch/fastText <https://github.com/facebookresearch/fastText>__

Models

  • 最新的 英语单词向量 <https://fasttext.cc/docs/en/english-vectors.html>__。
  • 针对 157 种语言的单词向量,基于维基百科和网络爬取数据训练 <https://github.com/facebookresearch/fastText/blob/master/docs/crawl-vectors.md>__。
  • 用于 语言识别 <https://fasttext.cc/docs/en/language-identification.html#content>__ 和 各种监督任务 <https://fasttext.cc/docs/en/supervised-models.html#content>__ 的模型。

Supplementary data :

  • 预处理过的 YFCC100M 数据 <https://fasttext.cc/docs/en/dataset.html#content>__ .

FAQ

您可以在其项目 网站 <https://fasttext.cc/>__ 上找到 常见问题解答 <https://fasttext.cc/docs/en/faqs.html#content>__。

Cheatsheet

此外,还提供了充满实用单行代码的 速查表 <https://fasttext.cc/docs/en/cheatsheet.html#content>__。

Weighted Words

Term frequency

词频是“词袋模型”(Bag of words),这是一种最简单的文本特征提取技术之一。该方法基于统计每个文档中的单词数量并将其分配给特征空间。


Term Frequency-Inverse Document Frequency

Tf-idf 给出的文档中术语权重的数学表示如下:

.. image:: docs/eq/tf-idf.gif :width: 10px

其中 N 是文档数量,df(t) 是语料库中包含术语 t 的文档数量。第一部分可以提高召回率,而第二部分可以提高词嵌入(word embedding)的精确度。尽管 Tf-idf 试图克服文档中常见术语的问题,但它仍然受到一些其他描述性限制的影响。即,Tf-idf 无法解释文档中单词之间的相似性,因为每个单词都作为一个索引呈现。近年来,随着更复杂模型(如神经网络)的发展,出现了新的方法,可以整合诸如单词相似性和词性标注(part of speech tagging)等概念。本工作使用了 word2vec 和 GloVe,这两种是最常用于深度学习技术的常见方法。

.. code:: python

from sklearn.feature_extraction.text import TfidfVectorizer
def loadData(X_train, X_test,MAX_NB_WORDS=75000):
    vectorizer_x = TfidfVectorizer(max_features=MAX_NB_WORDS)
    X_train = vectorizer_x.fit_transform(X_train).toarray()
    X_test = vectorizer_x.transform(X_test).toarray()
    print("tf-idf with",str(np.array(X_train).shape[1]),"features")
    return (X_train,X_test)
Comparison of Feature Extraction Techniques

+---------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+ | 模型 | 优势 | 局限性 | +---------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+ | 加权词 | * 易于计算 | * 无法捕捉文本中的位置信息 (syntactic / 句法) | | | | | | | * 使用该方法易于计算两个文档之间的相似度 | * 无法捕捉文本中的含义 (semantics / 语义) | | | | | | | * 提取文档中最具描述性术语的基本指标 | | | | | * 常见词对结果的影响(例如,“am”, “is”等) | | | * 适用于未知词汇(例如语言中的新词) | | +---------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+ | TF-IDF | * 易于计算 | * 无法捕捉文本中的位置信息 (syntactic / 句法) | | | | | | | | | | | * 使用该方法易于计算两个文档之间的相似度 | * 无法捕捉文本中的含义 (semantics / 语义) | | | | | | | | | | | * 提取文档中最具描述性术语的基本指标 | | | | | | | | | | | | * 由于 IDF,常见词不会影响结果(例如,“am”, “is”等) | | +---------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+ | Word2Vec | * 捕捉文本中单词的位置 (syntactic / 句法) | * 无法从文本中捕捉单词的含义(无法捕捉 polysemy / 多义性) | | | | | | | * 捕捉单词中的含义 (semantics / 语义) | * 无法捕捉 corpus (语料库) 中的未登录词 | +---------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+ | GloVe (预训练) | * 捕捉文本中单词的位置 (syntactic / 句法) | * 无法从文本中捕捉单词的含义(无法捕捉 polysemy / 多义性) | | | | | | | * 捕捉单词中的含义 (semantics / 语义) | | | | | * 存储内存消耗 | | | * 在大型 corpus (语料库) 上训练 | | | | | | | | | * 无法捕捉 corpus (语料库) 中的未登录词 | +---------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+ | GloVe (训练) | * 非常直接,例如,强制词向量捕捉向量空间中的亚线性关系(表现优于 Word2Vec) | * 存储内存消耗 | | | | | | | * 高频词对的权重较低,如 stop words (停用词) 如“am”, “is”等。不会主导训练进程 | * 需要大型 corpus (语料库) 进行学习 | | | | | | | | * 无法捕捉 corpus (语料库) 中的未登录词 | | | | | | | | * 无法从文本中捕捉单词的含义(无法捕捉 polysemy / 多义性) | +---------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+ | FastText | * 适用于稀有词(其字符 n-grams (n-gram) 与其他词共享) | * 无法从文本中捕捉单词的含义(无法捕捉 polysemy / 多义性) | | | | | | | | * 存储内存消耗 | | | * 通过字符级别的 n-gram 解决未登录词问题 | | | | | * 与 GloVe 和 Word2Vec 相比,计算成本更高 | +---------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+ |上下文相关的词表示| * 从文本中捕捉单词的含义(结合上下文,处理 polysemy / 多义性) | * 存储内存消耗 | | | | | | | | * 显著改善 downstream tasks (下游任务) 的性能。与其他方法相比计算成本更高 | | | | | | | | * 需要为所有 LSTM 和 feedforward layers (前馈层) 提供另一个词嵌入 | | | | | | | | * 无法捕捉 corpus (语料库) 中的未登录词 | | | | | | | | | | | | * 仅适用于句子和文档级别(无法用于单个词级别) | +---------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------+

======================== 降维


主成分分析 (PCA)

主成分分析(Principal Component Analysis,简称 PCA)是多变量分析和降维中最流行的技术。PCA 是一种识别数据近似所在的子空间的方法。这意味着找到不相关的新变量,并最大化方差以尽可能保留更多的变异性。

在文本数据集(20newsgroups)上对 tf-idf(词频 - 逆文档频率,具有 75000 个特征)进行 PCA 降至 2000 个分量的示例:

.. code:: python

from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np

def TFIDF(X_train, X_test, MAX_NB_WORDS=75000):
    vectorizer_x = TfidfVectorizer(max_features=MAX_NB_WORDS)
    X_train = vectorizer_x.fit_transform(X_train).toarray()
    X_test = vectorizer_x.transform(X_test).toarray()
    print("tf-idf with", str(np.array(X_train).shape[1]), "features")
    return (X_train, X_test)


from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

X_train,X_test = TFIDF(X_train,X_test)

from sklearn.decomposition import PCA
pca = PCA(n_components=2000)
X_train_new = pca.fit_transform(X_train)
X_test_new = pca.transform(X_test)

print("train with old features: ",np.array(X_train).shape)
print("train with new features:" ,np.array(X_train_new).shape)

print("test with old features: ",np.array(X_test).shape)
print("test with new features:" ,np.array(X_test_new).shape)

输出:

.. code:: python

tf-idf with 75000 features
train with old features:  (11314, 75000)
train with new features: (11314, 2000)
test with old features:  (7532, 75000)
test with new features: (7532, 2000)
线性判别分析 (LDA)

线性判别分析(Linear Discriminant Analysis,简称 LDA)是另一种常用于数据分类和降维的技术。当类内频率不相等时,LDA 特别有用,并且其性能已在随机生成的测试数据上进行了评估。类依赖和类独立转换是 LDA 中的两种方法,分别使用类间方差与类内方差的比率以及总体方差与类内方差的比率。

.. code:: python

from sklearn.feature_extraction.text import TfidfVectorizer import numpy as np from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

def TFIDF(X_train, X_test, MAX_NB_WORDS=75000): vectorizer_x = TfidfVectorizer(max_features=MAX_NB_WORDS) X_train = vectorizer_x.fit_transform(X_train).toarray() X_test = vectorizer_x.transform(X_test).toarray() print("tf-idf with", str(np.array(X_train).shape[1]), "features") return (X_train, X_test)

from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train') newsgroups_test = fetch_20newsgroups(subset='test') X_train = newsgroups_train.data X_test = newsgroups_test.data y_train = newsgroups_train.target y_test = newsgroups_test.target

X_train,X_test = TFIDF(X_train,X_test)

LDA = LinearDiscriminantAnalysis(n_components=15) X_train_new = LDA.fit(X_train,y_train) X_train_new = LDA.transform(X_train) X_test_new = LDA.transform(X_test)

print("train with old features: ",np.array(X_train).shape) print("train with new features:" ,np.array(X_train_new).shape)

print("test with old features: ",np.array(X_test).shape) print("test with new features:" ,np.array(X_test_new).shape)

输出:

.. code::

tf-idf with 75000 features
train with old features:  (11314, 75000)
train with new features: (11314, 15)
test with old features:  (7532, 75000)
test with new features: (7532, 15)
非负矩阵分解 (NMF)

.. code:: python

from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
from sklearn.decomposition import NMF


def TFIDF(X_train, X_test, MAX_NB_WORDS=75000):
    vectorizer_x = TfidfVectorizer(max_features=MAX_NB_WORDS)
    X_train = vectorizer_x.fit_transform(X_train).toarray()
    X_test = vectorizer_x.transform(X_test).toarray()
    print("tf-idf with", str(np.array(X_train).shape[1]), "features")
    return (X_train, X_test)


from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

X_train,X_test = TFIDF(X_train,X_test)



NMF_ = NMF(n_components=2000)
X_train_new = NMF_.fit(X_train)
X_train_new =  NMF_.transform(X_train)
X_test_new = NMF_.transform(X_test)

print("train with old features: ",np.array(X_train).shape)
print("train with new features:" ,np.array(X_train_new).shape)

print("test with old features: ",np.array(X_test).shape)
print("test with new features:" ,np.array(X_test_new))

输出:

.. code::

tf-idf with 75000 features
train with old features:  (11314, 75000)
train with new features: (11314, 2000)
test with old features:  (7532, 75000)
test with new features: (7532, 2000)
随机投影

随机投影(Random Projection)或随机特征主要用于超大规模数据集或非常高维特征空间的降维技术。文本和文档,特别是带有加权特征提取时,可能包含大量的潜在特征。 许多研究人员针对文本数据挖掘、文本分类和/或降维应用了随机投影技术。 我们开始回顾一些随机投影技术。

.. image:: docs/pic/Random%20Projection.png

.. code:: python

from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np

def TFIDF(X_train, X_test, MAX_NB_WORDS=75000):
    vectorizer_x = TfidfVectorizer(max_features=MAX_NB_WORDS)
    X_train = vectorizer_x.fit_transform(X_train).toarray()
    X_test = vectorizer_x.transform(X_test).toarray()
    print("tf-idf with", str(np.array(X_train).shape[1]), "features")
    return (X_train, X_test)


from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train') newsgroups_test = fetch_20newsgroups(subset='test') X_train = newsgroups_train.data X_test = newsgroups_test.data y_train = newsgroups_train.target y_test = newsgroups_test.target

X_train,X_test = TFIDF(X_train,X_test)

from sklearn import random_projection

RandomProjection = random_projection.GaussianRandomProjection(n_components=2000)
X_train_new = RandomProjection.fit_transform(X_train)
X_test_new = RandomProjection.transform(X_test)

print("train with old features: ",np.array(X_train).shape)
print("train with new features:" ,np.array(X_train_new).shape)

print("test with old features: ",np.array(X_test).shape)
print("test with new features:" ,np.array(X_test_new).shape)

输出:

.. code:: python

tf-idf with 75000 features
train with old features:  (11314, 75000)
train with new features: (11314, 2000)
test with old features:  (7532, 75000)
test with new features: (7532, 2000)
Autoencoder(自编码器)

Autoencoder(自编码器)是一种神经网络技术,旨在尝试将其输入映射到其输出。作为降维方法,Autoencoder 通过神经网络的强大表示能力取得了巨大成功。主要思想是,在输入层和输出层之间使用一个神经元较少的隐藏层来降低特征空间的维度。特别是对于包含许多特征的文本、文档和序列,Autoencoder 可以帮助更快、更高效地处理数据。

.. image:: docs/pic/Autoencoder.png

.. code:: python

from keras.layers import Input, Dense from keras.models import Model

this is the size of our encoded representations

encoding_dim = 1500

this is our input placeholder

input = Input(shape=(n,))

"encoded" is the encoded representation of the input

encoded = Dense(encoding_dim, activation='relu')(input)

"decoded" is the lossy reconstruction of the input

decoded = Dense(n, activation='sigmoid')(encoded)

this model maps an input to its reconstruction

autoencoder = Model(input, decoded)

this model maps an input to its encoded representation

encoder = Model(input, encoded)

encoded_input = Input(shape=(encoding_dim,))

retrieve the last layer of the autoencoder model

decoder_layer = autoencoder.layers[-1]

create the decoder model

decoder = Model(encoded_input, decoder_layer(encoded_input))

autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')

加载数据:

.. code:: python

autoencoder.fit(x_train, x_train, epochs=50, batch_size=256, shuffle=True, validation_data=(x_test, x_test))

T-分布随机邻域嵌入 (T-SNE)

T-分布随机邻域嵌入 (T-SNE) 是一种用于嵌入高维数据的非线性降维技术,主要用于在低维空间中进行可视化。该方法基于 G. Hinton and ST. Roweis <https://www.cs.toronto.edu/~fritz/absps/sne.pdf>__ 。SNE 通过将高维欧氏距离转换为表示相似度的条件概率来工作。

示例 <http://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html>__:

.. code:: python

import numpy as np from sklearn.manifold import TSNE X = np.array([[0, 0, 0], [0, 1, 1], [1, 0, 1], [1, 1, 1]]) X_embedded = TSNE(n_components=2).fit_transform(X) X_embedded.shape

Glove 和 T-SNE 在文本上的示例:

.. image:: docs/pic/TSNE.png

=============================== 文本分类技术


Rocchio 分类法

Rocchio 算法的第一个版本由 rocchio 于 1971 年引入,用于查询全文数据库时的相关性反馈。此后,许多研究人员针对文本和文档分类解决并开发了该技术。该方法使用每个信息词的 TF-IDF 权重代替一组布尔特征。通过使用文档训练集,Rocchio 算法为每个类别构建一个原型向量,该向量属于特定类别的所有训练文档向量的平均向量。然后,它将每个测试文档分配给与每个原型向量之间具有最大相似度的类别。

当在最近的质心分类器中使用时,我们将 tf-idf 向量用作文本分类的输入数据,该分类器被称为 Rocchio 分类器。

.. code:: python

from sklearn.neighbors.nearest_centroid import NearestCentroid
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', NearestCentroid()),
                     ])

text_clf.fit(X_train, y_train)


predicted = text_clf.predict(X_test)

print(metrics.classification_report(y_test, predicted))

输出:

.. code:: python

              precision    recall  f1-score   support

          0       0.75      0.49      0.60       319
          1       0.44      0.76      0.56       389
          2       0.75      0.68      0.71       394
          3       0.71      0.59      0.65       392
          4       0.81      0.71      0.76       385
          5       0.83      0.66      0.74       395
          6       0.49      0.88      0.63       390
          7       0.86      0.76      0.80       396
          8       0.91      0.86      0.89       398
          9       0.85      0.79      0.82       397
         10       0.95      0.80      0.87       399
         11       0.94      0.66      0.78       396
         12       0.40      0.70      0.51       393
         13       0.84      0.49      0.62       396
         14       0.89      0.72      0.80       394
         15       0.55      0.73      0.63       398
         16       0.68      0.76      0.71       364
         17       0.97      0.70      0.81       376
         18       0.54      0.53      0.53       310
         19       0.58      0.39      0.47       251

avg / total 0.74 0.69 0.70 7532

提升与装袋

提升

.. image:: docs/pic/Boosting.PNG

Boosting(提升) 是一种主要用于减少监督学习中方差的集成学习(Ensemble learning)元算法。它基本上是一族将弱学习器转化为强学习器的机器学习算法。提升基于 Michael Kearns <https://en.wikipedia.org/wiki/Michael_Kearns_(computer_scientist)>__ 和 Leslie Valiant (1988, 1989) 提出的问题:一组弱学习器能否创建一个单一的强学习器?弱学习器被定义为一种仅与真实分类略有相关的分类器(它可以比随机猜测更好地标记示例)。相比之下,强学习器是一种与真实分类任意高度相关的分类器。

.. code:: python

from sklearn.ensemble import GradientBoostingClassifier from sklearn.pipeline import Pipeline from sklearn import metrics from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train') newsgroups_test = fetch_20newsgroups(subset='test') X_train = newsgroups_train.data X_test = newsgroups_test.data y_train = newsgroups_train.target y_test = newsgroups_test.target

text_clf = Pipeline([('vect', CountVectorizer()), ('tfidf', TfidfTransformer()), ('clf', GradientBoostingClassifier(n_estimators=100)), ])

text_clf.fit(X_train, y_train)

predicted = text_clf.predict(X_test)

print(metrics.classification_report(y_test, predicted))

输出:

.. code:: python

           precision    recall  f1-score   support
        0       0.81      0.66      0.73       319
        1       0.69      0.70      0.69       389
        2       0.70      0.68      0.69       394
        3       0.64      0.72      0.68       392
        4       0.79      0.79      0.79       385
        5       0.83      0.64      0.72       395
        6       0.81      0.84      0.82       390
        7       0.84      0.75      0.79       396
        8       0.90      0.86      0.88       398
        9       0.90      0.85      0.88       397
       10       0.93      0.86      0.90       399
       11       0.90      0.81      0.85       396
       12       0.33      0.69      0.45       393
       13       0.87      0.72      0.79       396
       14       0.87      0.84      0.85       394
       15       0.85      0.87      0.86       398
       16       0.65      0.78      0.71       364
       17       0.96      0.74      0.84       376
       18       0.70      0.55      0.62       310
       19       0.62      0.56      0.59       251

avg / total 0.78 0.75 0.76 7532


装袋

.. image:: docs/pic/Bagging.PNG

.. code:: python

from sklearn.ensemble import BaggingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', BaggingClassifier(KNeighborsClassifier())),
                     ])

text_clf.fit(X_train, y_train)


predicted = text_clf.predict(X_test)

print(metrics.classification_report(y_test, predicted))

输出:

.. code:: python

           precision    recall  f1-score   support
        0       0.57      0.74      0.65       319
        1       0.60      0.56      0.58       389
        2       0.62      0.54      0.58       394
        3       0.54      0.57      0.55       392
        4       0.63      0.54      0.58       385
        5       0.68      0.62      0.65       395
        6       0.55      0.46      0.50       390
        7       0.77      0.67      0.72       396
        8       0.79      0.82      0.80       398
        9       0.74      0.77      0.76       397
       10       0.81      0.86      0.83       399
       11       0.74      0.85      0.79       396
       12       0.67      0.49      0.57       393
       13       0.78      0.51      0.62       396
       14       0.76      0.78      0.77       394
       15       0.71      0.81      0.76       398
       16       0.73      0.73      0.73       364
       17       0.64      0.79      0.71       376
       18       0.45      0.69      0.54       310
       19       0.61      0.54      0.57       251

avg / total 0.67 0.67 0.67 7532

朴素贝叶斯分类器

朴素贝叶斯文本分类在工业界和学术界已使用很长时间(由 Thomas Bayes 在 1701-1761 年间引入)。然而,该技术自 1950 年代起就被用于文本和文档分类研究。朴素贝叶斯分类器(NBC)是一种生成模型,广泛用于信息检索。许多研究人员针对其应用解决并开发了这项技术。我们从 NBC 的最基础版本开始,该版本通过使用词频(词袋)特征提取技术,通过统计文档中的单词数量来实现。

.. code:: python

from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', MultinomialNB()),
                     ])

text_clf.fit(X_train, y_train)


predicted = text_clf.predict(X_test)

print(metrics.classification_report(y_test, predicted))

输出:

.. code:: python

精确率 召回率 F1 分数 支持度

          0       0.80      0.52      0.63       319
          1       0.81      0.65      0.72       389
          2       0.82      0.65      0.73       394
          3       0.67      0.78      0.72       392
          4       0.86      0.77      0.81       385
          5       0.89      0.75      0.82       395
          6       0.93      0.69      0.80       390
          7       0.85      0.92      0.88       396
          8       0.94      0.93      0.93       398
          9       0.92      0.90      0.91       397
         10       0.89      0.97      0.93       399
         11       0.59      0.97      0.74       396
         12       0.84      0.60      0.70       393
         13       0.92      0.74      0.82       396
         14       0.84      0.89      0.87       394
         15       0.44      0.98      0.61       398
         16       0.64      0.94      0.76       364
         17       0.93      0.91      0.92       376
         18       0.96      0.42      0.58       310
         19       0.97      0.14      0.24       251

平均/总计       0.82      0.77      0.77      7532
K 近邻算法 (K-nearest Neighbor)

R 在机器学习 (machine learning) 中,k 近邻算法 (k-nearest neighbors algorithm, kNN) 是一种用于分类的非参数技术 (non-parametric technique)。 该方法在过去几十年的许多研究中被用作自然语言处理 (Natural-language processing, NLP) 中的文本分类 (text classification) 技术。

.. image:: docs/pic/KNN.png

.. code:: python

from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', KNeighborsClassifier()),
                     ])

text_clf.fit(X_train, y_train)

predicted = text_clf.predict(X_test)

print(metrics.classification_report(y_test, predicted))

输出:

.. code:: python

               precision    recall  f1-score   support

          0       0.43      0.76      0.55       319
          1       0.50      0.61      0.55       389
          2       0.56      0.57      0.57       394
          3       0.53      0.58      0.56       392
          4       0.59      0.56      0.57       385
          5       0.69      0.60      0.64       395
          6       0.58      0.45      0.51       390
          7       0.75      0.69      0.72       396
          8       0.84      0.81      0.82       398
          9       0.77      0.72      0.74       397
         10       0.85      0.84      0.84       399
         11       0.76      0.84      0.80       396
         12       0.70      0.50      0.58       393
         13       0.82      0.49      0.62       396
         14       0.79      0.76      0.78       394
         15       0.75      0.76      0.76       398
         16       0.70      0.73      0.72       364
         17       0.62      0.76      0.69       376
         18       0.55      0.61      0.58       310
         19       0.56      0.49      0.52       251

avg / total       0.67      0.66      0.66      7532
支持向量机 (Support Vector Machine, SVM)

SVM 的原始版本由 Vapnik 和 Chervonenkis 于 1963 年提出。20 世纪 90 年代初,非线性版本由 BE. Boser 等人提出。SVM 的原始版本是为二分类问题 (binary classification problem) 设计的,但许多研究人员利用这一权威技术进行了多分类问题 (multi-class problem) 的研究。

支持向量机的优势基于 scikit-learn 页面:

  • 在高维空间 (high dimensional spaces) 中有效。
  • 在维度数量大于样本数量的情况下仍然有效。
  • 在决策函数 (decision function) 中使用训练点的一个子集(称为支持向量 (support vectors)),因此它也具有内存效率 (memory efficient)。
  • 多功能:可以为决策函数指定不同的核函数 (Kernel functions)。提供了常见的核函数,但也可能指定自定义核 (custom kernels)。

支持向量机的缺点包括:

  • 如果特征 (features) 数量远大于样本 (samples) 数量,通过选择核函数和正则化项 (regularization term) 来避免过拟合 (over-fitting) 至关重要。
  • SVM 不直接提供概率估计 (probability estimates),这些是通过昂贵的五折交叉验证 (five-fold cross-validation) 计算得出的(见下面的“得分与概率”)。

.. image:: docs/pic/SVM.png

.. code:: python

from sklearn.svm import LinearSVC
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', LinearSVC()),
                     ])

text_clf.fit(X_train, y_train)


predicted = text_clf.predict(X_test)

print(metrics.classification_report(y_test, predicted))

输出:

.. code:: python

               precision    recall  f1-score   support

0 0.82 0.80 0.81 319 1 0.76 0.80 0.78 389 2 0.77 0.73 0.75 394 3 0.71 0.76 0.74 392 4 0.84 0.86 0.85 385 5 0.87 0.76 0.81 395 6 0.83 0.91 0.87 390 7 0.92 0.91 0.91 396 8 0.95 0.95 0.95 398 9 0.92 0.95 0.93 397 10 0.96 0.98 0.97 399 11 0.93 0.94 0.93 396 12 0.81 0.79 0.80 393 13 0.90 0.87 0.88 396 14 0.90 0.93 0.92 394 15 0.84 0.93 0.88 398 16 0.75 0.92 0.82 364 17 0.97 0.89 0.93 376 18 0.82 0.62 0.71 310 19 0.75 0.61 0.68 251

avg / total       0.85      0.85      0.85      7532
决策树

文本和数据挖掘中较早的分类算法之一是决策树。决策树分类器(Decision Tree Classifiers, DTC's)在许多不同的分类领域都得到了成功应用。该技术的结构包括数据空间的层次分解(仅针对训练数据集)。决策树作为分类任务由 D. Morgan <http://www.aclweb.org/anthology/P95-1037>__ 引入,并由 JR. Quinlan <https://courses.cs.ut.ee/2009/bayesian-networks/extras/quinlan1986.pdf>__ 开发。主要思想是基于数据点的属性创建树,但挑战在于确定哪个属性应处于父级,哪个应处于子级。为了解决这个问题,De Mantaras <https://link.springer.com/article/10.1023/A:1022694001379>__ 引入了用于树中特征选择的统计建模。

.. code:: python

from sklearn import tree
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', tree.DecisionTreeClassifier()),
                     ])

text_clf.fit(X_train, y_train)


predicted = text_clf.predict(X_test)

print(metrics.classification_report(y_test, predicted))

输出:

.. code:: python

               precision    recall  f1-score   support

          0       0.51      0.48      0.49       319
          1       0.42      0.42      0.42       389
          2       0.51      0.56      0.53       394
          3       0.46      0.42      0.44       392
          4       0.50      0.56      0.53       385
          5       0.50      0.47      0.48       395
          6       0.66      0.73      0.69       390
          7       0.60      0.59      0.59       396
          8       0.66      0.72      0.69       398
          9       0.53      0.55      0.54       397
         10       0.68      0.66      0.67       399
         11       0.73      0.69      0.71       396
         12       0.34      0.33      0.33       393
         13       0.52      0.42      0.46       396
         14       0.65      0.62      0.63       394
         15       0.68      0.72      0.70       398
         16       0.49      0.62      0.55       364
         17       0.78      0.60      0.68       376
         18       0.38      0.38      0.38       310
         19       0.32      0.32      0.32       251

avg / total       0.55      0.55      0.55      7532
随机森林

随机森林(Random Forests)或随机决策森林技术是一种用于文本分类的集成学习方法(Ensemble Learning Method)。该方法于 1995 年由 T. Kam Ho <https://doi.org/10.1109/ICDAR.1995.598994>__ 首次提出,当时使用了 t 棵树并行运行。后来该技术由 L. Breiman <https://link.springer.com/article/10.1023/A:1010933404324>__ 在 1999 年进一步发展,他们发现其作为随机森林(RF)的边界度量是收敛的。

.. image:: docs/pic/RF.png

.. code:: python

from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import Pipeline
from sklearn import metrics
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.datasets import fetch_20newsgroups

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', RandomForestClassifier(n_estimators=100)),
                     ])

text_clf.fit(X_train, y_train)


predicted = text_clf.predict(X_test)

print(metrics.classification_report(y_test, predicted))

输出:

.. code:: python

                precision    recall  f1-score   support

0 0.69 0.63 0.66 319 1 0.56 0.69 0.62 389 2 0.67 0.78 0.72 394 3 0.67 0.67 0.67 392 4 0.71 0.78 0.74 385 5 0.78 0.68 0.73 395 6 0.74 0.92 0.82 390 7 0.81 0.79 0.80 396 8 0.90 0.89 0.90 398 9 0.80 0.89 0.84 397 10 0.90 0.93 0.91 399 11 0.89 0.91 0.90 396 12 0.68 0.49 0.57 393 13 0.83 0.65 0.73 396 14 0.81 0.88 0.84 394 15 0.68 0.91 0.78 398 16 0.67 0.86 0.75 364 17 0.93 0.78 0.85 376 18 0.86 0.48 0.61 310 19 0.79 0.31 0.45 251

avg / total       0.77      0.76      0.75      7532
条件随机场(CRF)

条件随机场(CRF)是一种无向图模型,如图所示。CRF 定义了给定观测序列 X 的标签序列 Y 的条件概率,即 P(Y|X)。CRF 通过对标签序列的条件概率而非联合概率 P(X,Y) 进行建模,可以在不违反独立性假设的情况下整合观测序列的复杂特征。计算 P(X|Y) 时使用了“团”(clique,即完全连接的子图)的概念以及团势。考虑到图中每个团都有一个势函数,变量配置的概率对应于一系列非负势函数的乘积。每个势函数计算出的值等同于其对应团中的变量采取特定配置的概率。

.. image:: docs/pic/CRF.png

示例来自 此处 <http://sklearn-crfsuite.readthedocs.io/en/latest/tutorial.html>__ 让我们使用 CoNLL 2002 数据来构建一个命名实体识别(NER)系统 CoNLL2002 语料库可在 NLTK 中找到。我们使用西班牙语数据。

.. code:: python

  import nltk
  import sklearn_crfsuite
  from sklearn_crfsuite import metrics
  nltk.corpus.conll2002.fileids()
  train_sents = list(nltk.corpus.conll2002.iob_sents('esp.train'))
  test_sents = list(nltk.corpus.conll2002.iob_sents('esp.testb'))
  
  

sklearn-crfsuite(以及 python-crfsuite)支持多种特征格式;此处我们使用特征字典。

.. code:: python

  def word2features(sent, i):
      word = sent[i][0]
      postag = sent[i][1]

      features = {
          'bias': 1.0,
          'word.lower()': word.lower(),
          'word[-3:]': word[-3:],
          'word[-2:]': word[-2:],
          'word.isupper()': word.isupper(),
          'word.istitle()': word.istitle(),
          'word.isdigit()': word.isdigit(),
          'postag': postag,
          'postag[:2]': postag[:2],
      }
      if i > 0:
          word1 = sent[i-1][0]
          postag1 = sent[i-1][1]
          features.update({
              '-1:word.lower()': word1.lower(),
              '-1:word.istitle()': word1.istitle(),
              '-1:word.isupper()': word1.isupper(),
              '-1:postag': postag1,
              '-1:postag[:2]': postag1[:2],
          })
      else:
          features['BOS'] = True

      if i < len(sent)-1:
          word1 = sent[i+1][0]
          postag1 = sent[i+1][1]
          features.update({
              '+1:word.lower()': word1.lower(),
              '+1:word.istitle()': word1.istitle(),
              '+1:word.isupper()': word1.isupper(),
              '+1:postag': postag1,
              '+1:postag[:2]': postag1[:2],
          })
      else:
          features['EOS'] = True

      return features


  def sent2features(sent):
      return [word2features(sent, i) for i in range(len(sent))]

  def sent2labels(sent):
      return [label for token, postag, label in sent]

  def sent2tokens(sent):
      return [token for token, postag, label in sent]

  X_train = [sent2features(s) for s in train_sents]
  y_train = [sent2labels(s) for s in train_sents]

  X_test = [sent2features(s) for s in test_sents]
  y_test = [sent2labels(s) for s in test_sents]

要查看所有可能的 CRF 参数,请检查其文档字符串。此处我们使用 L-BFGS 训练算法(默认)配合 Elastic Net(L1 + L2)正则化。

.. code:: python

  crf = sklearn_crfsuite.CRF(
      algorithm='lbfgs',
      c1=0.1,
      c2=0.1,
      max_iterations=100,
      all_possible_transitions=True
  )
  crf.fit(X_train, y_train)

评估

.. code:: python

  y_pred = crf.predict(X_test)
  print(metrics.flat_classification_report(
      y_test, y_pred,  digits=3
  ))

输出:

.. code:: python

                 precision    recall  f1-score   support

        B-LOC      0.810     0.784     0.797      1084
       B-MISC      0.731     0.569     0.640       339
        B-ORG      0.807     0.832     0.820      1400
        B-PER      0.850     0.884     0.867       735
        I-LOC      0.690     0.637     0.662       325
       I-MISC      0.699     0.589     0.639       557
        I-ORG      0.852     0.786     0.818      1104
        I-PER      0.893     0.943     0.917       634
            O      0.992     0.997     0.994     45355

  avg / total      0.970     0.971     0.971     51533
深度学习

深度神经网络

深度神经网络(Deep Neural Networks)架构设计为通过多层连接进行学习,其中每一层仅在隐藏部分接收来自前一层的连接,并仅提供给下一层连接。输入是特征空间(feature space)的连接(如“特征提取”部分所述,与第一个隐藏层相关)。对于深度神经网络(DNN),输入层可以是 tf-idf、词嵌入(word embedding)等,如图中的标准 DNN 所示。输出层包含的神经元(neurons)数量等于多分类(multi-class classification)中的类别数,而二分类(binary classification)中仅有一个神经元。但本文的主要贡献在于我们拥有许多经过训练的 DNN 以服务于不同的目的。在此,我们有多分类 DNN,其中每个学习模型是随机生成的(每层的节点数以及层数都是随机分配的)。我们对深度神经网络(DNN)的实现基本上是一个判别式训练模型,使用标准的反向传播算法(back-propagation algorithm)以及 Sigmoid 或 ReLU 作为激活函数(activation functions)。用于多分类的输出层应使用 Softmax。

.. image:: docs/pic/DNN.png

导入包:

.. code:: python

from sklearn.datasets import fetch_20newsgroups
from keras.layers import  Dropout, Dense
from keras.models import Sequential
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
from sklearn import metrics

将文本转换为 TF-IDF:

.. code:: python

def TFIDF(X_train, X_test,MAX_NB_WORDS=75000):
    vectorizer_x = TfidfVectorizer(max_features=MAX_NB_WORDS)
    X_train = vectorizer_x.fit_transform(X_train).toarray()
    X_test = vectorizer_x.transform(X_test).toarray()
    print("tf-idf with",str(np.array(X_train).shape[1]),"features")
    return (X_train,X_test)

构建用于文本的 DNN 模型:

.. code:: python

def Build_Model_DNN_Text(shape, nClasses, dropout=0.5):
    """
    buildModel_DNN_Tex(shape, nClasses,dropout)
    Build Deep neural networks Model for text classification
    Shape is input feature space
    nClasses is number of classes
    """
    model = Sequential()
    node = 512 # number of nodes
    nLayers = 4 # number of  hidden layer

    model.add(Dense(node,input_dim=shape,activation='relu'))
    model.add(Dropout(dropout))
    for i in range(0,nLayers):
        model.add(Dense(node,input_dim=node,activation='relu'))
        model.add(Dropout(dropout))
    model.add(Dense(nClasses, activation='softmax'))

    model.compile(loss='sparse_categorical_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy'])

    return model

加载文本数据集(20newsgroups):

.. code:: python

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

运行 DNN 并查看我们的结果:

.. code:: python

X_train_tfidf,X_test_tfidf = TFIDF(X_train,X_test)
model_DNN = Build_Model_DNN_Text(X_train_tfidf.shape[1], 20)
model_DNN.fit(X_train_tfidf, y_train,
                              validation_data=(X_test_tfidf, y_test),
                              epochs=10,
                              batch_size=128,
                              verbose=2)

predicted = model_DNN.predict_class(X_test_tfidf)

print(metrics.classification_report(y_test, predicted))

模型摘要:

.. code:: python

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 512)               38400512  
_________________________________________________________________
dropout_1 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 512)               262656    
_________________________________________________________________
dropout_2 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_3 (Dense)              (None, 512)               262656    
_________________________________________________________________
dropout_3 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_4 (Dense)              (None, 512)               262656    
_________________________________________________________________
dropout_4 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_5 (Dense)              (None, 512)               262656    
_________________________________________________________________
dropout_5 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_6 (Dense)              (None, 20)                10260     
=================================================================
Total params: 39,461,396
Trainable params: 39,461,396
Non-trainable params: 0
_________________________________________________________________

输出:

.. code:: python

    Train on 11314 samples, validate on 7532 samples
    Epoch 1/10
     - 16s - loss: 2.7553 - acc: 0.1090 - val_loss: 1.9330 - val_acc: 0.3184
    Epoch 2/10
     - 15s - loss: 1.5330 - acc: 0.4222 - val_loss: 1.1546 - val_acc: 0.6204
    Epoch 3/10
     - 15s - loss: 0.7438 - acc: 0.7257 - val_loss: 0.8405 - val_acc: 0.7499
    Epoch 4/10
     - 15s - loss: 0.2967 - acc: 0.9020 - val_loss: 0.9214 - val_acc: 0.7767
    Epoch 5/10
     - 15s - loss: 0.1557 - acc: 0.9543 - val_loss: 0.8965 - val_acc: 0.7917
    Epoch 6/10
     - 15s - loss: 0.1015 - acc: 0.9705 - val_loss: 0.9427 - val_acc: 0.7949
    Epoch 7/10
     - 15s - loss: 0.0595 - acc: 0.9835 - val_loss: 0.9893 - val_acc: 0.7995
    Epoch 8/10
     - 15s - loss: 0.0495 - acc: 0.9866 - val_loss: 0.9512 - val_acc: 0.8079
    Epoch 9/10
     - 15s - loss: 0.0437 - acc: 0.9867 - val_loss: 0.9690 - val_acc: 0.8117
    Epoch 10/10
     - 15s - loss: 0.0443 - acc: 0.9880 - val_loss: 1.0004 - val_acc: 0.8070


                   precision    recall  f1-score   support

0 0.76 0.78 0.77 319 1 0.67 0.80 0.73 389 2 0.82 0.63 0.71 394 3 0.76 0.69 0.72 392 4 0.65 0.86 0.74 385 5 0.84 0.75 0.79 395 6 0.82 0.87 0.84 390 7 0.86 0.90 0.88 396 8 0.95 0.91 0.93 398 9 0.91 0.92 0.92 397 10 0.98 0.92 0.95 399 11 0.96 0.85 0.90 396 12 0.71 0.69 0.70 393 13 0.95 0.70 0.81 396 14 0.86 0.91 0.88 394 15 0.85 0.90 0.87 398 16 0.79 0.84 0.81 364 17 0.99 0.77 0.87 376 18 0.58 0.75 0.65 310 19 0.52 0.60 0.55 251

    avg / total       0.82      0.81      0.81      7532

循环神经网络 (RNN)

.. image:: docs/pic/RNN.png

研究人员针对文本模仿和分类提出的另一种神经网络(Neural Network)架构是循环神经网络(Recurrent Neural Networks,简称 RNN)。RNN 为序列中先前的数据点分配更高的权重。因此,该技术是一种强大的文本、字符串和序列数据分类方法。此外,正如本工作所示,该技术也可用于图像分类。在 RNN 中,神经网络以一种非常复杂的方法考虑先前节点的信息,这使得对数据集中的结构进行更好的语义分析成为可能。

门控循环单元 (GRU)


**门控循环单元**(Gated Recurrent Unit,简称 GRU)是 RNN 的一种门控机制,由 `J. Chung et al. <https://arxiv.org/abs/1412.3555>`__ 和 `K.Cho et al. <https://arxiv.org/abs/1406.1078>`__ 提出。GRU 是 **LSTM**(长短期记忆网络)架构的简化变体,但存在以下区别:GRU 包含两个门,且不拥有任何内部记忆(如图示所示);最后,不应用第二个非线性激活函数(图中的 tanh)。

.. image:: docs/pic/LSTM.png

长短期记忆网络 (LSTM)

长短期记忆网络(Long Short-Term Memory,简称 LSTM)由 S. Hochreiter and J. Schmidhuber <https://www.mitpressjournals.org/doi/abs/10.1162/neco.1997.9.8.1735>__ 提出,并由许多研究科学家开发。

为了应对这些问题,长短期记忆网络(LSTM)是一种特殊的 RNN,与基本 RNN 相比,它能以更有效的方式保留长期依赖关系。这对于克服梯度消失问题(vanishing gradient problem)特别有用。虽然 LSTM 具有类似于 RNN 的链式结构,但 LSTM 使用多个门来仔细调节允许进入每个节点状态的信息量。图示展示了 LSTM 模型的基本单元。

导入包:

.. code:: python

from keras.layers import Dropout, Dense, GRU, Embedding
from keras.models import Sequential
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
from sklearn import metrics
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from sklearn.datasets import fetch_20newsgroups

将文本转换为词嵌入(使用 GloVe):

.. code:: python

def loadData_Tokenizer(X_train, X_test,MAX_NB_WORDS=75000,MAX_SEQUENCE_LENGTH=500):
    np.random.seed(7)
    text = np.concatenate((X_train, X_test), axis=0)
    text = np.array(text)
    tokenizer = Tokenizer(num_words=MAX_NB_WORDS)
    tokenizer.fit_on_texts(text)
    sequences = tokenizer.texts_to_sequences(text)
    word_index = tokenizer.word_index
    text = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)
    print('Found %s unique tokens.' % len(word_index))
    indices = np.arange(text.shape[0])
    # np.random.shuffle(indices)
    text = text[indices]
    print(text.shape)
    X_train = text[0:len(X_train), ]
    X_test = text[len(X_train):, ]
    embeddings_index = {}
    f = open(".\\Glove\\glove.6B.50d.txt", encoding="utf8")
    for line in f:

        values = line.split()
        word = values[0]
        try:
            coefs = np.asarray(values[1:], dtype='float32')
        except:
            pass
        embeddings_index[word] = coefs
    f.close()
    print('Total %s word vectors.' % len(embeddings_index))
    return (X_train, X_test, word_index,embeddings_index)

构建用于文本的 RNN 模型:

.. code:: python

def Build_Model_RNN_Text(word_index, embeddings_index, nclasses,  MAX_SEQUENCE_LENGTH=500, EMBEDDING_DIM=50, dropout=0.5):
    """
    def buildModel_RNN(word_index, embeddings_index, nclasses,  MAX_SEQUENCE_LENGTH=500, EMBEDDING_DIM=50, dropout=0.5):
    word_index in word index ,
    embeddings_index is embeddings index, look at data_helper.py
    nClasses is number of classes,
    MAX_SEQUENCE_LENGTH is maximum lenght of text sequences
    """

    model = Sequential()
    hidden_layer = 3
    gru_node = 32

    embedding_matrix = np.random.random((len(word_index) + 1, EMBEDDING_DIM))
    for word, i in word_index.items():
        embedding_vector = embeddings_index.get(word)
        if embedding_vector is not None:
            # words not found in embedding index will be all-zeros.
            if len(embedding_matrix[i]) != len(embedding_vector):
                print("could not broadcast input array from shape", str(len(embedding_matrix[i])),
                      "into shape", str(len(embedding_vector)), " Please make sure your"
                                                                " EMBEDDING_DIM is equal to embedding_vector file ,GloVe,")
                exit(1)
            embedding_matrix[i] = embedding_vector
    model.add(Embedding(len(word_index) + 1,
                                EMBEDDING_DIM,
                                weights=[embedding_matrix],
                                input_length=MAX_SEQUENCE_LENGTH,
                                trainable=True))

print(gru_node) for i in range(0,hidden_layer): model.add(GRU(gru_node,return_sequences=True, recurrent_dropout=0.2)) model.add(Dropout(dropout)) model.add(GRU(gru_node, recurrent_dropout=0.2)) model.add(Dropout(dropout)) model.add(Dense(256, activation='relu')) model.add(Dense(nclasses, activation='softmax'))

    model.compile(loss='sparse_categorical_crossentropy',
                      optimizer='adam',
                      metrics=['accuracy'])
    return model

运行 RNN(循环神经网络)并查看我们的结果:

.. code:: python

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

X_train_Glove,X_test_Glove, word_index,embeddings_index = loadData_Tokenizer(X_train,X_test)


model_RNN = Build_Model_RNN_Text(word_index,embeddings_index, 20)

model_RNN.fit(X_train_Glove, y_train,
                              validation_data=(X_test_Glove, y_test),
                              epochs=10,
                              batch_size=128,
                              verbose=2)

predicted = model_RNN.predict_classes(X_test_Glove)

print(metrics.classification_report(y_test, predicted))

模型摘要:

.. code:: python

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_1 (Embedding)      (None, 500, 50)           8960500   
_________________________________________________________________
gru_1 (GRU)                  (None, 500, 256)          235776    
_________________________________________________________________
dropout_1 (Dropout)          (None, 500, 256)          0         
_________________________________________________________________
gru_2 (GRU)                  (None, 500, 256)          393984    
_________________________________________________________________
dropout_2 (Dropout)          (None, 500, 256)          0         
_________________________________________________________________
gru_3 (GRU)                  (None, 500, 256)          393984    
_________________________________________________________________
dropout_3 (Dropout)          (None, 500, 256)          0         
_________________________________________________________________
gru_4 (GRU)                  (None, 256)               393984    
_________________________________________________________________
dense_1 (Dense)              (None, 20)                5140      
=================================================================
Total params: 10,383,368
Trainable params: 10,383,368
Non-trainable params: 0
_________________________________________________________________

输出:

.. code:: python

Train on 11314 samples, validate on 7532 samples
Epoch 1/20
 - 268s - loss: 2.5347 - acc: 0.1792 - val_loss: 2.2857 - val_acc: 0.2460
Epoch 2/20
 - 271s - loss: 1.6751 - acc: 0.3999 - val_loss: 1.4972 - val_acc: 0.4660
Epoch 3/20
 - 270s - loss: 1.0945 - acc: 0.6072 - val_loss: 1.3232 - val_acc: 0.5483
Epoch 4/20
 - 269s - loss: 0.7761 - acc: 0.7312 - val_loss: 1.1009 - val_acc: 0.6452
Epoch 5/20
 - 269s - loss: 0.5513 - acc: 0.8112 - val_loss: 1.0395 - val_acc: 0.6832
Epoch 6/20
 - 269s - loss: 0.3765 - acc: 0.8754 - val_loss: 0.9977 - val_acc: 0.7086
Epoch 7/20
 - 270s - loss: 0.2481 - acc: 0.9202 - val_loss: 1.0485 - val_acc: 0.7270
Epoch 8/20
 - 269s - loss: 0.1717 - acc: 0.9463 - val_loss: 1.0269 - val_acc: 0.7394
Epoch 9/20
 - 269s - loss: 0.1130 - acc: 0.9644 - val_loss: 1.1498 - val_acc: 0.7369
Epoch 10/20
 - 269s - loss: 0.0640 - acc: 0.9808 - val_loss: 1.1442 - val_acc: 0.7508
Epoch 11/20
 - 269s - loss: 0.0567 - acc: 0.9828 - val_loss: 1.2318 - val_acc: 0.7414
Epoch 12/20
 - 268s - loss: 0.0472 - acc: 0.9858 - val_loss: 1.2204 - val_acc: 0.7496
Epoch 13/20
 - 269s - loss: 0.0319 - acc: 0.9910 - val_loss: 1.1895 - val_acc: 0.7657
Epoch 14/20
 - 268s - loss: 0.0466 - acc: 0.9853 - val_loss: 1.2821 - val_acc: 0.7517
Epoch 15/20
 - 271s - loss: 0.0269 - acc: 0.9917 - val_loss: 1.2869 - val_acc: 0.7557
Epoch 16/20
 - 271s - loss: 0.0187 - acc: 0.9950 - val_loss: 1.3037 - val_acc: 0.7598
Epoch 17/20
 - 268s - loss: 0.0157 - acc: 0.9959 - val_loss: 1.2974 - val_acc: 0.7638
Epoch 18/20
 - 270s - loss: 0.0121 - acc: 0.9966 - val_loss: 1.3526 - val_acc: 0.7602
Epoch 19/20
 - 269s - loss: 0.0262 - acc: 0.9926 - val_loss: 1.4182 - val_acc: 0.7517
Epoch 20/20
 - 269s - loss: 0.0249 - acc: 0.9918 - val_loss: 1.3453 - val_acc: 0.7638


               precision    recall  f1-score   support

          0       0.71      0.71      0.71       319
          1       0.72      0.68      0.70       389
          2       0.76      0.62      0.69       394
          3       0.67      0.58      0.62       392
          4       0.68      0.67      0.68       385
          5       0.75      0.73      0.74       395
          6       0.82      0.74      0.78       390
          7       0.83      0.83      0.83       396
          8       0.81      0.90      0.86       398
          9       0.92      0.90      0.91       397
         10       0.91      0.94      0.93       399
         11       0.87      0.76      0.81       396
         12       0.57      0.70      0.63       393
         13       0.81      0.85      0.83       396
         14       0.74      0.93      0.82       394
         15       0.82      0.83      0.83       398
         16       0.74      0.78      0.76       364
         17       0.96      0.83      0.89       376
         18       0.64      0.60      0.62       310
         19       0.48      0.56      0.52       251

avg / total       0.77      0.76      0.76      7532

卷积神经网络 (CNN)

另一种应用于层次化文档分类的深度学习架构是卷积神经网络 (Convolutional Neural Networks, CNN)。虽然最初是为图像处理构建的,其架构类似于视觉皮层,但 CNN 也被有效地用于文本分类。在用于图像处理的基础 CNN 中,图像张量与一组大小为 d 乘 d 的卷积核进行卷积运算。这些卷积层被称为特征图 (feature maps),可以堆叠起来为输入提供多个滤波器。为了降低计算复杂度,CNN 使用池化 (pooling) 技术,从而减小网络中从一层传递到下一层的输出尺寸。使用不同的池化技术可以在减少输出的同时保留重要特征。

最常见的池化方法是最大池化 (max pooling),即从池化窗口中选择最大元素。为了将堆叠特征图的池化输出馈送到下一层,这些图被展平为一列。CNN 中的最终层通常是全连接密集层 (fully connected dense layers)。

一般来说,在卷积神经网络的反向传播 (back-propagation) 步骤中,不仅权重 (weights) 会被调整,特征检测器滤波器 (feature detector filters) 也会被调整。用于文本的 CNN 的一个潜在问题是“通道”(channels) 的数量,Sigma(特征空间的大小)。对于文本而言,这个数字可能非常大(例如 50K),而对于图像则问题较小(例如仅有 3 个 RGB 通道)。这意味着用于文本的 CNN 的维度 (dimensionality) 非常高。

.. image:: docs/pic/CNN.png

导入包:

.. code:: python

from keras.layers import Dropout, Dense,Input,Embedding,Flatten, MaxPooling1D, Conv1D
from keras.models import Sequential,Model
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
from sklearn import metrics
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from sklearn.datasets import fetch_20newsgroups
from keras.layers.merge import Concatenate

将文本转换为词嵌入 (使用 GloVe):

.. code:: python

def loadData_Tokenizer(X_train, X_test,MAX_NB_WORDS=75000,MAX_SEQUENCE_LENGTH=500):
    np.random.seed(7)
    text = np.concatenate((X_train, X_test), axis=0)
    text = np.array(text)
    tokenizer = Tokenizer(num_words=MAX_NB_WORDS)
    tokenizer.fit_on_texts(text)
    sequences = tokenizer.texts_to_sequences(text)
    word_index = tokenizer.word_index
    text = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)
    print('Found %s unique tokens.' % len(word_index))
    indices = np.arange(text.shape[0])
    # np.random.shuffle(indices)
    text = text[indices]
    print(text.shape)
    X_train = text[0:len(X_train), ]
    X_test = text[len(X_train):, ]
    embeddings_index = {}
    f = open(".\\Glove\\glove.6B.50d.txt", encoding="utf8")
    for line in f:
        values = line.split()
        word = values[0]
        try:
            coefs = np.asarray(values[1:], dtype='float32')
        except:
            pass
        embeddings_index[word] = coefs
    f.close()
    print('Total %s word vectors.' % len(embeddings_index))
    return (X_train, X_test, word_index,embeddings_index)

构建用于文本的 CNN 模型:

.. code:: python

def Build_Model_CNN_Text(word_index, embeddings_index, nclasses, MAX_SEQUENCE_LENGTH=500, EMBEDDING_DIM=50, dropout=0.5):

    """
        def buildModel_CNN(word_index, embeddings_index, nclasses, MAX_SEQUENCE_LENGTH=500, EMBEDDING_DIM=50, dropout=0.5):
        word_index in word index ,
        embeddings_index is embeddings index, look at data_helper.py
        nClasses is number of classes,
        MAX_SEQUENCE_LENGTH is maximum lenght of text sequences,
        EMBEDDING_DIM is an int value for dimention of word embedding look at data_helper.py
    """

    model = Sequential()
    embedding_matrix = np.random.random((len(word_index) + 1, EMBEDDING_DIM))
    for word, i in word_index.items():
        embedding_vector = embeddings_index.get(word)
        if embedding_vector is not None:
            # words not found in embedding index will be all-zeros.
            if len(embedding_matrix[i]) !=len(embedding_vector):
                print("could not broadcast input array from shape",str(len(embedding_matrix[i])),
                                 "into shape",str(len(embedding_vector))," Please make sure your"
                                 " EMBEDDING_DIM is equal to embedding_vector file ,GloVe,")
                exit(1)

            embedding_matrix[i] = embedding_vector

    embedding_layer = Embedding(len(word_index) + 1,
                                EMBEDDING_DIM,
                                weights=[embedding_matrix],
                                input_length=MAX_SEQUENCE_LENGTH,
                                trainable=True)

    # applying a more complex convolutional approach
    convs = []
    filter_sizes = []
    layer = 5
    print("Filter  ",layer)
    for fl in range(0,layer):
        filter_sizes.append((fl+2))

    node = 128
    sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32')
    embedded_sequences = embedding_layer(sequence_input)

    for fsz in filter_sizes:
        l_conv = Conv1D(node, kernel_size=fsz, activation='relu')(embedded_sequences)
        l_pool = MaxPooling1D(5)(l_conv)
        #l_pool = Dropout(0.25)(l_pool)
        convs.append(l_pool)

    l_merge = Concatenate(axis=1)(convs)
    l_cov1 = Conv1D(node, 5, activation='relu')(l_merge)
    l_cov1 = Dropout(dropout)(l_cov1)
    l_pool1 = MaxPooling1D(5)(l_cov1)
    l_cov2 = Conv1D(node, 5, activation='relu')(l_pool1)
    l_cov2 = Dropout(dropout)(l_cov2)
    l_pool2 = MaxPooling1D(30)(l_cov2)
    l_flat = Flatten()(l_pool2)
    l_dense = Dense(1024, activation='relu')(l_flat)
    l_dense = Dropout(dropout)(l_dense)
    l_dense = Dense(512, activation='relu')(l_dense)
    l_dense = Dropout(dropout)(l_dense)
    preds = Dense(nclasses, activation='softmax')(l_dense)
    model = Model(sequence_input, preds)

    model.compile(loss='sparse_categorical_crossentropy',
                  optimizer='adam',
                  metrics=['accuracy'])



    return model

运行 CNN 并查看我们的结果:

.. code:: python

newsgroups_train = fetch_20newsgroups(subset='train')
newsgroups_test = fetch_20newsgroups(subset='test')
X_train = newsgroups_train.data
X_test = newsgroups_test.data
y_train = newsgroups_train.target
y_test = newsgroups_test.target

X_train_Glove,X_test_Glove, word_index,embeddings_index = loadData_Tokenizer(X_train,X_test)


model_CNN = Build_Model_CNN_Text(word_index,embeddings_index, 20)

model_CNN.summary()

model_CNN.fit(X_train_Glove, y_train,
                              validation_data=(X_test_Glove, y_test),
                              epochs=15,
                              batch_size=128,
                              verbose=2)

predicted = model_CNN.predict(X_test_Glove)

predicted = np.argmax(predicted, axis=1)


print(metrics.classification_report(y_test, predicted))

模型:

.. code:: python

__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            (None, 500)          0                                            
__________________________________________________________________________________________________
embedding_1 (Embedding)         (None, 500, 50)      8960500     input_1[0][0]                    
__________________________________________________________________________________________________
conv1d_1 (Conv1D)               (None, 499, 128)     12928       embedding_1[0][0]                
__________________________________________________________________________________________________
conv1d_2 (Conv1D)               (None, 498, 128)     19328       embedding_1[0][0]                
__________________________________________________________________________________________________
conv1d_3 (Conv1D)               (None, 497, 128)     25728       embedding_1[0][0]                
__________________________________________________________________________________________________
conv1d_4 (Conv1D)               (None, 496, 128)     32128       embedding_1[0][0]                
__________________________________________________________________________________________________
conv1d_5 (Conv1D)               (None, 495, 128)     38528       embedding_1[0][0]                
__________________________________________________________________________________________________
max_pooling1d_1 (MaxPooling1D)  (None, 99, 128)      0           conv1d_1[0][0]                   
__________________________________________________________________________________________________
max_pooling1d_2 (MaxPooling1D)  (None, 99, 128)      0           conv1d_2[0][0]                   
__________________________________________________________________________________________________
max_pooling1d_3 (MaxPooling1D)  (None, 99, 128)      0           conv1d_3[0][0]                   
__________________________________________________________________________________________________
max_pooling1d_4 (MaxPooling1D)  (None, 99, 128)      0           conv1d_4[0][0]                   
__________________________________________________________________________________________________
max_pooling1d_5 (MaxPooling1D)  (None, 99, 128)      0           conv1d_5[0][0]                   
__________________________________________________________________________________________________
concatenate_1 (Concatenate)     (None, 495, 128)     0           max_pooling1d_1[0][0]            
                                                                 max_pooling1d_2[0][0]            
                                                                 max_pooling1d_3[0][0]            
                                                                 max_pooling1d_4[0][0]            
                                                                 max_pooling1d_5[0][0]            
__________________________________________________________________________________________________
conv1d_6 (Conv1D)               (None, 491, 128)     82048       concatenate_1[0][0]              
__________________________________________________________________________________________________
dropout_1 (Dropout)             (None, 491, 128)     0           conv1d_6[0][0]                   
__________________________________________________________________________________________________
max_pooling1d_6 (MaxPooling1D)  (None, 98, 128)      0           dropout_1[0][0]                  
__________________________________________________________________________________________________
conv1d_7 (Conv1D)               (None, 94, 128)      82048       max_pooling1d_6[0][0]            
__________________________________________________________________________________________________
dropout_2 (Dropout)             (None, 94, 128)      0           conv1d_7[0][0]                   
__________________________________________________________________________________________________
max_pooling1d_7 (MaxPooling1D)  (None, 3, 128)       0           dropout_2[0][0]                  
__________________________________________________________________________________________________
flatten_1 (Flatten)             (None, 384)          0           max_pooling1d_7[0][0]            
__________________________________________________________________________________________________
dense_1 (Dense)                 (None, 1024)         394240      flatten_1[0][0]                  
__________________________________________________________________________________________________
dropout_3 (Dropout)             (None, 1024)         0           dense_1[0][0]                    
__________________________________________________________________________________________________
dense_2 (Dense)                 (None, 512)          524800      dropout_3[0][0]                  
__________________________________________________________________________________________________
dropout_4 (Dropout)             (None, 512)          0           dense_2[0][0]                    
__________________________________________________________________________________________________
dense_3 (Dense)                 (None, 20)           10260       dropout_4[0][0]                  
==================================================================================================
Total params: 10,182,536
Trainable params: 10,182,536
Non-trainable params: 0
__________________________________________________________________________________________________

输出:

.. code:: python

在 11314 个样本上训练,在 7532 个样本上验证 Epoch 1/15 - 6s - 损失 (loss): 2.9329 - 准确率 (acc): 0.0783 - 验证集损失 (val_loss): 2.7628 - 验证集准确率 (val_acc): 0.1403 Epoch 2/15 - 4s - 损失:2.2534 - 准确率:0.2249 - 验证集损失:2.1715 - 验证集准确率:0.4007 Epoch 3/15 - 4s - 损失:1.5643 - 准确率:0.4326 - 验证集损失:1.7846 - 验证集准确率:0.5052 Epoch 4/15 - 4s - 损失:1.1771 - 准确率:0.5662 - 验证集损失:1.4949 - 验证集准确率:0.6131 Epoch 5/15 - 4s - 损失:0.8880 - 准确率:0.6797 - 验证集损失:1.3629 - 验证集准确率:0.6256 Epoch 6/15 - 4s - 损失:0.6990 - 准确率:0.7569 - 验证集损失:1.2013 - 验证集准确率:0.6624 Epoch 7/15 - 4s - 损失:0.5037 - 准确率:0.8200 - 验证集损失:1.0674 - 验证集准确率:0.6807 Epoch 8/15 - 4s - 损失:0.4050 - 准确率:0.8626 - 验证集损失:1.0223 - 验证集准确率:0.6863 Epoch 9/15 - 4s - 损失:0.2952 - 准确率:0.8968 - 验证集损失:0.9045 - 验证集准确率:0.7120 Epoch 10/15 - 4s - 损失:0.2314 - 准确率:0.9217 - 验证集损失:0.8574 - 验证集准确率:0.7326 Epoch 11/15 - 4s - 损失:0.1778 - 准确率:0.9436 - 验证集损失:0.8752 - 验证集准确率:0.7270 Epoch 12/15 - 4s - 损失:0.1475 - 准确率:0.9524 - 验证集损失:0.8299 - 验证集准确率:0.7355 Epoch 13/15 - 4s - 损失:0.1089 - 准确率:0.9657 - 验证集损失:0.8034 - 验证集准确率:0.7491 Epoch 14/15 - 4s - 损失:0.1047 - 准确率:0.9666 - 验证集损失:0.8172 - 验证集准确率:0.7463 Epoch 15/15 - 4s - 损失:0.0749 - 准确率:0.9774 - 验证集损失:0.8511 - 验证集准确率:0.7313

               精确率 (precision)    召回率 (recall)  F1 分数 (f1-score)   支持数 (support)

          0       0.75      0.61      0.67       319
          1       0.63      0.74      0.68       389
          2       0.74      0.54      0.62       394
          3       0.49      0.76      0.60       392
          4       0.60      0.70      0.64       385
          5       0.79      0.57      0.66       395
          6       0.73      0.76      0.74       390
          7       0.83      0.74      0.78       396
          8       0.86      0.88      0.87       398
          9       0.95      0.78      0.86       397
         10       0.93      0.93      0.93       399
         11       0.92      0.77      0.84       396
         12       0.55      0.72      0.62       393
         13       0.76      0.85      0.80       396
         14       0.86      0.83      0.84       394
         15       0.91      0.73      0.81       398
         16       0.75      0.65      0.70       364
         17       0.95      0.86      0.90       376
         18       0.60      0.49      0.54       310
         19       0.37      0.60      0.46       251

平均 / 总计       0.76      0.73      0.74      7532

层次化注意力网络 (Hierarchical Attention Networks)

.. image:: docs/pic/HAN.png


循环卷积神经网络 (Recurrent Convolutional Neural Networks, RCNN)

循环卷积神经网络 (RCNN) 也用于文本分类。该技术的主要思想是利用循环结构捕捉上下文信息,并使用卷积神经网络构建文本表示。该架构结合了 RNN(循环神经网络)和 CNN(卷积神经网络)的优点,在一个模型中利用两者的优势。

导入包:

.. code:: python

  from keras.preprocessing import sequence
  from keras.models import Sequential
  from keras.layers import Dense, Dropout, Activation
  from keras.layers import Embedding
  from keras.layers import GRU
  from keras.layers import Conv1D, MaxPooling1D
  from keras.datasets import imdb
  from sklearn.datasets import fetch_20newsgroups
  import numpy as np
  from sklearn import metrics
  from keras.preprocessing.text import Tokenizer
  from keras.preprocessing.sequence import pad_sequences

将文本转换为词嵌入(使用 GloVe):

.. code:: python

  def loadData_Tokenizer(X_train, X_test,MAX_NB_WORDS=75000,MAX_SEQUENCE_LENGTH=500):
      np.random.seed(7)
      text = np.concatenate((X_train, X_test), axis=0)
      text = np.array(text)
      tokenizer = Tokenizer(num_words=MAX_NB_WORDS)
      tokenizer.fit_on_texts(text)
      sequences = tokenizer.texts_to_sequences(text)
      word_index = tokenizer.word_index
      text = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)
      print('Found %s unique tokens.' % len(word_index))
      indices = np.arange(text.shape[0])
      # np.random.shuffle(indices)
      text = text[indices]
      print(text.shape)
      X_train = text[0:len(X_train), ]
      X_test = text[len(X_train):, ]
      embeddings_index = {}
      f = open("C:\\Users\\kamran\\Documents\\GitHub\\RMDL\\Examples\\Glove\\glove.6B.50d.txt", encoding="utf8")
      for line in f:
          values = line.split()
          word = values[0]
          try:
              coefs = np.asarray(values[1:], dtype='float32')
          except:
              pass
          embeddings_index[word] = coefs
      f.close()
      print('Total %s word vectors.' % len(embeddings_index))
      return (X_train, X_test, word_index,embeddings_index)

.. code:: python

  def Build_Model_RCNN_Text(word_index, embeddings_index, nclasses, MAX_SEQUENCE_LENGTH=500, EMBEDDING_DIM=50):

      kernel_size = 2
      filters = 256
      pool_size = 2
      gru_node = 256

      embedding_matrix = np.random.random((len(word_index) + 1, EMBEDDING_DIM))
      for word, i in word_index.items():
          embedding_vector = embeddings_index.get(word)
          if embedding_vector is not None:
              # words not found in embedding index will be all-zeros.
              if len(embedding_matrix[i]) !=len(embedding_vector):
                  print("could not broadcast input array from shape",str(len(embedding_matrix[i])),
                                   "into shape",str(len(embedding_vector))," Please make sure your"
                                   " EMBEDDING_DIM is equal to embedding_vector file ,GloVe,")
                  exit(1)

              embedding_matrix[i] = embedding_vector

model = Sequential() model.add(Embedding(len(word_index) + 1, EMBEDDING_DIM, weights=[embedding_matrix], input_length=MAX_SEQUENCE_LENGTH, trainable=True)) model.add(Dropout(0.25)) model.add(Conv1D(filters, kernel_size, activation='relu')) model.add(MaxPooling1D(pool_size=pool_size)) model.add(Conv1D(filters, kernel_size, activation='relu')) model.add(MaxPooling1D(pool_size=pool_size)) model.add(Conv1D(filters, kernel_size, activation='relu')) model.add(MaxPooling1D(pool_size=pool_size)) model.add(Conv1D(filters, kernel_size, activation='relu')) model.add(MaxPooling1D(pool_size=pool_size)) model.add(LSTM(gru_node, return_sequences=True, recurrent_dropout=0.2)) model.add(LSTM(gru_node, return_sequences=True, recurrent_dropout=0.2)) model.add(LSTM(gru_node, return_sequences=True, recurrent_dropout=0.2)) model.add(LSTM(gru_node, recurrent_dropout=0.2)) model.add(Dense(1024,activation='relu')) model.add(Dense(nclasses)) model.add(Activation('softmax'))

      model.compile(loss='sparse_categorical_crossentropy',
                    optimizer='adam',
                    metrics=['accuracy'])

      return model

.. code:: python

  newsgroups_train = fetch_20newsgroups(subset='train')
  newsgroups_test = fetch_20newsgroups(subset='test')
  X_train = newsgroups_train.data
  X_test = newsgroups_test.data
  y_train = newsgroups_train.target
  y_test = newsgroups_test.target

  X_train_Glove,X_test_Glove, word_index,embeddings_index = loadData_Tokenizer(X_train,X_test)

运行 RCNN:

.. code:: python

  model_RCNN = Build_Model_CNN_Text(word_index,embeddings_index, 20)


  model_RCNN.summary()

  model_RCNN.fit(X_train_Glove, y_train,
                                validation_data=(X_test_Glove, y_test),
                                epochs=15,
                                batch_size=128,
                                verbose=2)

  predicted = model_RCNN.predict(X_test_Glove)

  predicted = np.argmax(predicted, axis=1)
  print(metrics.classification_report(y_test, predicted))

模型摘要:

.. code:: python

  _________________________________________________________________
  Layer (type)                 Output Shape              Param #   
  =================================================================
  embedding_1 (Embedding)      (None, 500, 50)           8960500   
  _________________________________________________________________
  dropout_1 (Dropout)          (None, 500, 50)           0         
  _________________________________________________________________
  conv1d_1 (Conv1D)            (None, 499, 256)          25856     
  _________________________________________________________________
  max_pooling1d_1 (MaxPooling1 (None, 249, 256)          0         
  _________________________________________________________________
  conv1d_2 (Conv1D)            (None, 248, 256)          131328    
  _________________________________________________________________
  max_pooling1d_2 (MaxPooling1 (None, 124, 256)          0         
  _________________________________________________________________
  conv1d_3 (Conv1D)            (None, 123, 256)          131328    
  _________________________________________________________________
  max_pooling1d_3 (MaxPooling1 (None, 61, 256)           0         
  _________________________________________________________________
  conv1d_4 (Conv1D)            (None, 60, 256)           131328    
  _________________________________________________________________
  max_pooling1d_4 (MaxPooling1 (None, 30, 256)           0         
  _________________________________________________________________
  lstm_1 (LSTM)                (None, 30, 256)           525312    
  _________________________________________________________________
  lstm_2 (LSTM)                (None, 30, 256)           525312    
  _________________________________________________________________
  lstm_3 (LSTM)                (None, 30, 256)           525312    
  _________________________________________________________________
  lstm_4 (LSTM)                (None, 256)               525312    
  _________________________________________________________________
  dense_1 (Dense)              (None, 1024)              263168    
  _________________________________________________________________
  dense_2 (Dense)              (None, 20)                20500     
  _________________________________________________________________
  activation_1 (Activation)    (None, 20)                0         
  =================================================================
  Total params: 11,765,256
  Trainable params: 11,765,256
  Non-trainable params: 0
  _________________________________________________________________

输出:

.. code:: python

  Train on 11314 samples, validate on 7532 samples
  Epoch 1/15
   - 28s - loss: 2.6624 - acc: 0.1081 - val_loss: 2.3012 - val_acc: 0.1753
  Epoch 2/15
   - 22s - loss: 2.1142 - acc: 0.2224 - val_loss: 1.9168 - val_acc: 0.2669
  Epoch 3/15
   - 22s - loss: 1.7465 - acc: 0.3290 - val_loss: 1.8257 - val_acc: 0.3412
  Epoch 4/15
   - 22s - loss: 1.4730 - acc: 0.4356 - val_loss: 1.5433 - val_acc: 0.4436
  Epoch 5/15
   - 22s - loss: 1.1800 - acc: 0.5556 - val_loss: 1.2973 - val_acc: 0.5467
  Epoch 6/15
   - 22s - loss: 0.9910 - acc: 0.6281 - val_loss: 1.2530 - val_acc: 0.5797
  Epoch 7/15
   - 22s - loss: 0.8581 - acc: 0.6854 - val_loss: 1.1522 - val_acc: 0.6281
  Epoch 8/15
   - 22s - loss: 0.7058 - acc: 0.7428 - val_loss: 1.2385 - val_acc: 0.6033
  Epoch 9/15
   - 22s - loss: 0.6792 - acc: 0.7515 - val_loss: 1.0200 - val_acc: 0.6775
  Epoch 10/15
   - 22s - loss: 0.5782 - acc: 0.7948 - val_loss: 1.0961 - val_acc: 0.6577
  Epoch 11/15
   - 23s - loss: 0.4674 - acc: 0.8341 - val_loss: 1.0866 - val_acc: 0.6924
  Epoch 12/15
   - 23s - loss: 0.4284 - acc: 0.8512 - val_loss: 0.9880 - val_acc: 0.7096
  Epoch 13/15
   - 22s - loss: 0.3883 - acc: 0.8670 - val_loss: 1.0190 - val_acc: 0.7151
  Epoch 14/15
   - 22s - loss: 0.3334 - acc: 0.8874 - val_loss: 1.0025 - val_acc: 0.7232
  Epoch 15/15
   - 22s - loss: 0.2857 - acc: 0.9038 - val_loss: 1.0123 - val_acc: 0.7331


               precision    recall  f1-score   support

0 0.64 0.73 0.68 319 1 0.45 0.83 0.58 389 2 0.81 0.64 0.71 394 3 0.64 0.57 0.61 392 4 0.55 0.78 0.64 385 5 0.77 0.52 0.62 395 6 0.84 0.77 0.80 390 7 0.87 0.79 0.83 396 8 0.85 0.90 0.87 398 9 0.98 0.84 0.90 397 10 0.93 0.96 0.95 399 11 0.92 0.79 0.85 396 12 0.59 0.53 0.56 393 13 0.82 0.82 0.82 396 14 0.84 0.84 0.84 394 15 0.83 0.89 0.86 398 16 0.68 0.86 0.76 364 17 0.97 0.86 0.91 376 18 0.66 0.50 0.57 310 19 0.53 0.31 0.40 251

  avg / total       0.77      0.75      0.75      7532

随机多模型深度学习 (RMDL)

参考论文:RMDL: Random Multimodel Deep Learning for Classification <https://www.researchgate.net/publication/324922651_RMDL_Random_Multimodel_Deep_Learning_for_Classification>__

一种用于分类的新型集成 (Ensemble) 深度学习 (Deep Learning) 方法。深度学习 (Deep Learning) 模型在许多领域都取得了最先进的结果。RMDL 解决了寻找最佳深度学习 (Deep Learning) 结构和架构的问题,同时通过不同深度学习 (Deep Learning) 架构的集成提高了鲁棒性 (Robustness) 和准确率 (Accuracy)。RDML 可以接受多种数据作为输入,包括文本、视频、图像和符号。

|RMDL|

用于分类的随机多模型深度学习 (RDML) 架构。RMDL 包含 3 个随机模型,左侧为 oneDNN 分类器,中间为深度 CNN 分类器,右侧为深度 RNN 分类器(每个单元可以是 LSTM 或 GRU)。

安装

RMDL 的安装可以使用 pip 和 git:

使用 pip

.. code:: python

    pip install RMDL

使用 git

.. code:: bash

git clone --recursive https://github.com/kk7nc/RMDL.git

该软件包的主要要求是带有 Tensorflow 的 Python 3。requirements.txt 文件列出了安装所有要求所需的 Python 包 <https://www.scaler.com/topics/python/python-packages/>__,请运行以下命令:

.. code:: bash

pip -r install requirements.txt

或者

.. code:: bash

pip3  install -r requirements.txt

或者:

.. code:: bash

conda install --file requirements.txt

文档:

每年复杂数据集数量的指数级增长需要机器学习方法进一步增强,以提供稳健且准确的数据分类。最近,在图像分类、自然语言处理、人脸识别等任务上,深度学习 (Deep Learning) 方法相比以前的机器学习算法取得了更好的结果。这些深度学习 (Deep Learning) 算法的成功依赖于它们对数据内部复杂和非线性关系进行建模的能力。然而,为这些模型找到合适的结构一直是研究人员面临的挑战。本文介绍了随机多模型深度学习 (RMDL):一种用于分类的新型集成 (Ensemble) 深度学习 (Deep Learning) 方法。RMDL 旨在解决寻找最佳深度学习 (Deep Learning) 架构的问题,同时通过多个深度学习 (Deep Learning) 架构的集成提高鲁棒性 (Robustness) 和准确率 (Accuracy)。简而言之,RMDL 并行训练多个深度神经网络 (DNN)、卷积神经网络 (CNN) 和循环神经网络 (RNN) 模型,并组合它们的结果,以产生优于任何单个模型的结果。为了创建这些模型,每个深度学习 (Deep Learning) 模型在其神经网络结构的层数和节点数方面都是随机构建的。生成的 RDML 模型可用于各种领域,如文本、视频、图像和符号。在本项目中,我们深入描述了 RMDL 模型,并展示了图像和文本分类以及人脸识别的结果。对于图像分类,我们使用 MNIST 和 CIFAR-10 数据集将我们的模型与一些可用的基线进行了比较。同样,我们使用了四个数据集,即 WOS、Reuters、IMDB 和 20newsgroup,并将我们的结果与可用的基线进行了比较。Web of Science (WOS) 由作者收集,包含三组 (~小、中、大组)。最后,我们使用 ORL 数据集将我们方法的性能与其他人脸识别方法进行了比较。这些测试结果表​​明,RDML 模型在各种数据类型和分类问题上始终优于标准方法。


文本分层深度学习 (HDLTex)

参考论文:HDLTex: Hierarchical Deep Learning for Text Classification <https://arxiv.org/abs/1709.08267>__

|HDLTex|

文档:

日益庞大的文档集合需要改进的信息处理方法来搜索、检索和组织文本文档。这些信息处理方法的核心是文档分类,这已成为监督学习 (Supervised Learning) 旨在解决的重要任务。最近,随着文档数量的增加,传统监督分类器的性能有所下降。文档量的指数级增长也增加了类别的数量。本文以一种不同于当前文档分类方法的方式来解决这个问题,后者将问题视为多类分类 (Multi-class Classification)。相反,我们采用一种称为文本分类分层深度学习 (HDLTex) 的方法执行分层分类 (Hierarchical Classification)。HDLTex 采用堆叠的深度学习 (Deep Learning) 架构来提供对文档的分层理解。

文本分类算法比较

+------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ | 模型 | 优点 | 缺点 | +------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ | Rocchio 算法 | * 易于实现 | * 用户只能检索到少量相关文档 | | | | | | | * 计算成本非常低 | * Rocchio 算法常对多模态类别进行错误分类 | | | | | | | * 相关性反馈机制(有助于将不相关文档的排名降低) | * 该技术鲁棒性不强 | | | | | | | | * 该算法中的线性组合不适用于多类数据集 | +------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ | Boosting 和 Bagging | * 提高了稳定性和准确性(利用集成学习 (Ensemble learning) 的优势,多个弱分类器优于单个强分类器。) | * 计算复杂度高 | | | | | | | * 降低方差,有助于避免过拟合 (Overfitting) 问题。 | * 失去可解释性(如果模型数量过多,理解模型非常困难) | | | | | | | | * 需要仔细调整不同的超参数 (Hyper-parameters)。 | +------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ | 逻辑回归 | * 易于实现 | * 无法解决非线性问题 | | | | | | | * 不需要太多计算资源 | * 预测要求每个数据点相互独立 | | | | | | | * 不需要输入特征进行缩放(预处理) | * 试图基于一组独立变量预测结果 | | | | | | | * 不需要任何调参 | | +------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ | 朴素贝叶斯分类器 | * 在处理文本数据方面表现非常好 | * 对数据分布形状有强假设 | | | | | | | * 易于实现 | * 受限于数据稀缺,特征空间中任何可能值的似然值必须由频率学派估计 | | | | | | | * 与其他算法相比速度快 | | +------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ | K 近邻 (KNN) | * 对文本数据集有效 | * 该模型的计算成本非常高 | | | | | | | * 非参数 | * 难以找到最优的 k 值 | | | | | | | * 考虑了文本或文档的更多局部特征 | * 在寻找最近邻的大搜索问题中存在限制 | | | | | | | * 自然处理多类数据集 | * 对于文本数据集,找到一个有意义的距离函数很困难 | +------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ | 支持向量机 (SVM) | * SVM 可以建模非线性决策边界 | * 由于维度高导致结果缺乏透明度(尤其是文本数据)。 | | | | | | | * 当线性可分时,表现与逻辑回归相似 | * 选择高效的核函数很困难(取决于核函数,容易受到过拟合/训练问题的影响) | | | | | | | * 对过拟合问题具有鲁棒性~(特别是对于文本数据集,因为高维空间) | * 内存复杂度 | +------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ | 决策树 | * 可以轻松处理定性(类别)特征 | * 对角线决策边界存在问题 | | | | | | | * 与平行于特征轴的决策边界配合良好 | * 容易过拟合 | | | | | | | * 决策树在学习和预测方面都是非常快的算法 | * 对数据中的微小扰动极其敏感 | | | | | | | | * 样本外预测存在问题 | +------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ | 条件随机场 (CRF) | * 其特征设计灵活 | * 训练步骤的计算复杂度高 | | | | | | | * 由于 CRF 计算全局最优输出节点的条件概率,它克服了标签偏差的缺点 | * 该算法无法处理未知词汇 | | | | | | | * 结合了分类和图形建模的优势,能够紧凑地建模多元数据 | * 关于在线学习 (Online learning) 的问题(这使得当新数据可用时很难重新训练模型。) | +------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ | 随机森林 | * 与其他技术相比,决策树的集成训练非常快 | * 一旦训练完成,生成预测相当慢 | | | | | | | * 降低了方差(相对于普通树) | * 森林中更多的树增加了预测步骤的时间复杂度 | | | | | | | * 不需要准备和预处理输入数据 | * 不如其他方法易于直观解释 | | | | | | | | * 容易发生过度拟合 | | | | | | | | * 需要选择森林中树的数量 | +------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+ | 深度学习 (Deep Learning) | * 特征设计灵活(减少了对特征工程 (Feature engineering) 的需求,这是机器学习实践中最耗时的部分之一。) | * 需要大量数据(如果你只有小样本文本数据,深度学习不太可能优于其他方法。) | | | | | | | * 架构可适应新问题 | * 训练计算成本极高。 | | | | | | | * 可以处理复杂的输入输出映射 | * 模型可解释性是深度学习最重要的问题~(大多数时候深度学习是黑盒 (Black-box)) | | | | | | | * 可以轻松处理在线学习(这使得当新数据可用时很容易重新训练模型。) | * 找到高效的架构和结构仍然是该技术的主要挑战 | | | | | | | * 并行处理能力(它可以同时执行多项工作) | | +------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+

========== 评估


F1 分数 (F1 Score)

.. image:: docs/pic/F1.png

Matthews 相关系数 (Matthews Correlation Coefficient, MCC)

计算 Matthews 相关系数 (MCC)

Matthews 相关系数在机器学习中被用作衡量二分类(两类)问题质量的指标。它考虑了真阳性、假阳性、真阴性和假阴性,通常被认为是一种平衡的度量标准,即使类别大小差异很大也可以使用。MCC 本质上是一个介于 -1 和 +1 之间的相关系数值。+1 代表完美预测,0 代表平均随机预测,-1 代表反向预测。该统计量也被称为 phi 系数。

.. code:: python

from sklearn.metrics import matthews_corrcoef
y_true = [+1, +1, +1, -1]
y_pred = [+1, -1, +1, +1]
matthews_corrcoef(y_true, y_pred)  
接收者操作特征曲线 (Receiver Operating Characteristics, ROC)

ROC 曲线通常用于二分类中以研究分类器的输出。为了将 ROC 曲线和 ROC 面积扩展到多分类或多标签分类,需要对输出进行二值化。可以为每个标签绘制一条 ROC 曲线,也可以将标签指示矩阵的每个元素视为二元预测来绘制 ROC 曲线(微平均)。

多分类分类的另一种评估指标是宏平均,它为每个标签的分类赋予相等的权重。 [sources <http://scikit-learn.org/stable/auto_examples/model_selection/plot_roc.html>__]

.. code:: python

import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle

from sklearn import svm, datasets
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifier
from scipy import interp

# Import some data to play with
iris = datasets.load_iris()
X = iris.data
y = iris.target

# Binarize the output
y = label_binarize(y, classes=[0, 1, 2])
n_classes = y.shape[1]

# Add noisy features to make the problem harder
random_state = np.random.RandomState(0)
n_samples, n_features = X.shape
X = np.c_[X, random_state.randn(n_samples, 200 * n_features)]

# shuffle and split training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.5,
                                                    random_state=0)

# Learn to predict each class against the other
classifier = OneVsRestClassifier(svm.SVC(kernel='linear', probability=True,
                                 random_state=random_state))
y_score = classifier.fit(X_train, y_train).decision_function(X_test)

# Compute ROC curve and ROC area for each class
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(n_classes):
    fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i])
    roc_auc[i] = auc(fpr[i], tpr[i])

# Compute micro-average ROC curve and ROC area
fpr["micro"], tpr["micro"], _ = roc_curve(y_test.ravel(), y_score.ravel())
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"])

特定类别的 ROC 曲线图

.. code:: python

plt.figure()
lw = 2
plt.plot(fpr[2], tpr[2], color='darkorange',
         lw=lw, label='ROC curve (area = %0.2f)' % roc_auc[2])
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()

.. image:: /docs/pic/sphx_glr_plot_roc_001.png

曲线下面积 (Area Under Curve, AUC)

ROC 曲线下面积 (AUC) 是一个汇总指标,用于测量 ROC 曲线下方的整个区域。AUC 具有有用的属性,例如在方差分析 (ANOVA) 测试中增加灵敏度、独立于决策阈值、对先验类别概率不变以及对负类和正类关于决策索引的指示程度。

.. code:: python

  import numpy as np
  from sklearn import metrics
  fpr, tpr, thresholds = metrics.roc_curve(y, pred, pos_label=2)
  metrics.auc(fpr, tpr)

========================== 文本与文档数据集


IMDB
  • IMDB 数据集 <http://ai.stanford.edu/~amaas/data/sentiment/>__

来自 IMDB 的 25,000 条电影评论数据集,按情感(正面/负面)标记。评论已预处理,每条评论编码为单词索引序列(整数)。为了方便起见,单词按数据集中的总体频率进行索引,因此例如整数"3"编码数据中第 3 个最常见的单词。这允许快速过滤操作,例如“只考虑最常见的 10,000 个单词,但消除最常见的 20 个单词”。

按照惯例,“0”不代表特定单词,而是用于编码任何未知单词。

.. code:: python

from keras.datasets import imdb

(x_train, y_train), (x_test, y_test) = imdb.load_data(path="imdb.npz", num_words=None, skip_top=0, maxlen=None, seed=113, start_char=1, oov_char=2, index_from=3)

Reuters-21578
  • Reuters-21578 数据集 <https://keras.io/datasets/>__

来自路透社的 11,228 条新闻电文数据集,标记了 46 个主题。与 IMDB 数据集一样,每条电文编码为单词索引序列(相同约定)。

.. code:: python

from keras.datasets import reuters

(x_train, y_train), (x_test, y_test) = reuters.load_data(path="reuters.npz", num_words=None, skip_top=0, maxlen=None, test_split=0.2, seed=113, start_char=1, oov_char=2, index_from=3)

20Newsgroups
  • 20Newsgroups Dataset <https://archive.ics.uci.edu/ml/datasets/Twenty+Newsgroups>__

20 个新闻组数据集 (20 Newsgroups Dataset) 包含约 18000 条关于 20 个主题的帖子,分为两个子集:一个用于训练(或开发),另一个用于测试(或性能评估)。训练集和测试集之间的划分基于特定日期之前和之后发布的消息。

该模块包含两个加载器。第一个是 sklearn.datasets.fetch_20newsgroups (scikit-learn 数据集中获取 20 个新闻组的函数),它返回原始文本列表,这些文本可以馈送给文本特征提取器,例如带有自定义参数的 sklearn.feature_extraction.text.CountVectorizer (词频向量器),以提取特征向量。第二个是 sklearn.datasets.fetch_20newsgroups_vectorized,它返回现成的特征,即不需要使用特征提取器。

.. code:: python

from sklearn.datasets import fetch_20newsgroups newsgroups_train = fetch_20newsgroups(subset='train')

from pprint import pprint pprint(list(newsgroups_train.target_names))

['alt.atheism', 'comp.graphics', 'comp.os.ms-windows.misc', 'comp.sys.ibm.pc.hardware', 'comp.sys.mac.hardware', 'comp.windows.x', 'misc.forsale', 'rec.autos', 'rec.motorcycles', 'rec.sport.baseball', 'rec.sport.hockey', 'sci.crypt', 'sci.electronics', 'sci.med', 'sci.space', 'soc.religion.christian', 'talk.politics.guns', 'talk.politics.mideast', 'talk.politics.misc', 'talk.religion.misc']

Web of Science Dataset

数据集描述:

这里有三个数据集,包括 WOS-11967 , WOS-46985, 和 WOS-5736。每个文件夹包含以下内容:

  • X.txt
  • Y.txt
  • YL1.txt
  • YL2.txt

X 是包含文本序列的输入数据 Y 是目标值 YL1 是第一层级目标值(父标签) YL2 是第二层级目标值(子标签)

元数据: 此文件夹包含一个数据文件,属性如下: Y1 Y2 Y Domain area keywords Abstract

摘要 (Abstract) 是包含 46,985 篇已发表论文文本序列的输入数据 Y 是目标值 YL1 是第一层级目标值(父标签) YL2 是第二层级目标值(子标签) 领域 (Domain) 是主要领域,包含 7 个标签:{计算机科学,电气工程,心理学,机械工程,土木工程,医学科学,生物化学} 区域 (Area) 是论文的次级领域或区域,例如 CS->计算机图形学,包含 134 个标签。 关键词 (Keywords):是论文的作者关键词

  • Web of Science 数据集 WOS-11967 <http://dx.doi.org/10.17632/9rw3vkcfy4.2>__ ..

    此数据集包含 11,967 份文档,共 35 个类别,其中包括 7 个父类别。

  • Web of Science 数据集 WOS-46985 <http://dx.doi.org/10.17632/9rw3vkcfy4.2>__

..

此数据集包含 46,985 份文档,共 134 个类别,其中包括 7 个父类别。

  • Web of Science 数据集 WOS-5736 <http://dx.doi.org/10.17632/9rw3vkcfy4.2>__

..

此数据集包含 5,736 份文档,共 11 个类别,其中包括 3 个父类别。

参考文献:HDLTex: 用于文本分类的分层深度学习 (Hierarchical Deep Learning for Text Classification)

================================ 文本分类应用


信息检索

信息检索 (Information retrieval) 是从大量文档集合中找到满足信息需求的非结构化数据文档的过程。随着在线信息的快速增长,特别是文本格式的信息,文本分类 (text classification) 已成为管理此类数据的重要技术。该领域使用的一些重要方法包括朴素贝叶斯 (Naive Bayes)、支持向量机 (SVM)、决策树 (decision tree)、J48、k-近邻 (k-NN) 和 IBK。文档和文本数据集处理最具挑战性的应用之一是将文档分类方法应用于信息检索。

  • 🎓 信息检索简介 <http://eprints.bimcoordinator.co.uk/35/>__ Manning, C., Raghavan, P., & Schütze, H. (2010).

  • 🎓 网络论坛检索与文本分析:综述 <http://www.nowpublishers.com/article/Details/INR-062>__ Hoogeveen, Doris, et al.. (2018).

  • 🎓 信息检索中的自动文本分类:综述 <https://dl.acm.org/citation.cfm?id=2905191>__ Dwivedi, Sanjay K., and Chandrakala Arya.. (2016).

信息过滤

信息过滤 (Information filtering) 指的是从传入的数据流中选择相关信息或拒绝无关信息。信息过滤系统通常用于衡量和预测用户的长期兴趣。概率模型 (Probabilistic models),如贝叶斯推理网络 (Bayesian inference network),常用于信息过滤系统。贝叶斯推理网络采用递归推理将值传播通过推理网络,并返回排名最高的文档。Chris 使用带有迭代优化的向量空间模型 (vector space model) 进行过滤任务。

  • 🎓 搜索引擎:实践中的信息检索 <http://library.mpib-berlin.mpg.de/toc/z2009_2465.pdf/>__ Croft, W. B., Metzler, D., & Strohman, T. (2010).

  • 🎓 SMART 信息检索系统的实现 <https://ecommons.cornell.edu/bitstream/handle/1813/6526/85-686.pdf?sequence=1>__ Buckley, Chris

情感分析

情感分析 (Sentiment analysis) 是一种识别文本中观点、情感和主观性的计算方法。情感分类方法将与观点相关的文档分类为正面或负面。假设文档 d 表达了一个单一实体 e 的观点,且观点是通过单一观点持有者 h 形成的。朴素贝叶斯分类和支持向量机 (SVM) 是用于情感分类的最流行的监督学习方法 (supervised learning methods) 之一。术语及其各自频率、词性 (part of speech)、观点词汇和短语、否定词 (negations) 和句法依赖 (syntactic dependency) 等特征已被用于情感分类技术中。

  • 🎓 观点挖掘与情感分析 <http://www.nowpublishers.com/article/Details/INR-011>__ Pang, Bo, and Lillian Lee. (2008).

  • 🎓 意见挖掘与情感分析综述 <https://link.springer.com/chapter/10.1007/978-1-4614-3223-4_13>__ Liu, Bing, and Lei Zhang. (2010).

  • 🎓 点赞?:使用机器学习技术进行情感分类 <https://dl.acm.org/citation.cfm?id=1118704>__ Pang, Bo, Lillian Lee, and Shivakumar Vaithyanathan.

推荐系统

基于内容的推荐系统 (Content-based recommender systems) 根据项目的描述和用户兴趣的个人资料向用户推荐项目。用户的个人资料可以通过用户对项目的反馈(搜索查询历史或自我报告)以及个人资料中的自解释特征~(查询的过滤器或条件)来学习。通过这种方式,此类推荐系统的输入可以是半结构化的,即某些属性从自由文本字段中提取,而其他属性则直接指定。许多不同类型的文本分类方法已被用于建模用户偏好,例如决策树、最近邻方法、Rocchio 算法、线性分类器、概率方法和朴素贝叶斯 (Naive Bayes)。

  • 🎓 基于内容的推荐系统 <https://link.springer.com/chapter/10.1007/978-3-319-29659-3_4>__ Aggarwal, Charu C. (2016).

  • 🎓 基于内容的推荐系统 <https://link.springer.com/chapter/10.1007/978-3-540-72079-9_10>__ Pazzani, Michael J., and Daniel Billsus.

知识管理

文本数据库是信息和知识的重要来源。很大一部分企业信息(近 80%)存在于文本数据格式(非结构化)中。在知识提炼 (knowledge distillation) 中,模式或知识是从可以直接提取的形式中推断出来的,这些形式可以是半结构化的(例如概念图表示)或结构化/关系型数据表示)。给定的中间形式可以基于文档,其中每个实体代表特定领域中感兴趣的对象或概念。文档分类 (Document categorization) 是挖掘基于文档的中间形式的最常用方法之一。在其他研究中,文本分类被用于查找铁路事故原因与其在报告中对应描述之间的关系。

  • 🎓 文本挖掘:概念、应用、工具和问题——概述 <http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.403.2426&rep=rep1&type=pdf>__ Sumathy, K. L., and M. Chidambaram. (2013).

  • 🎓 使用深度学习分析铁路事故叙述 <https://ieeexplore.ieee.org/abstract/document/8614260/>__ Heidarysafa, Mojtaba, et al. (2018).

文档摘要

文本分类用于文档摘要,文档摘要可能会使用原始文档中未出现的单词或短语。由于在线信息迅速增加,多文档摘要 (Multi-document summarization) 也变得必要。因此,许多研究人员专注于使用文本分类从文档中提取重要特征的任务。

  • 🎓 自动文本摘要进展 <https://books.google.com/books?hl=en&lr=&id=YtUZQaKDmzEC&oi=fnd&pg=PA215&dq=Advances+in+automatic+text+summarization&ots=ZpvCsrG-dC&sig=8ecTDTrQR4mMzDnKvI58sowh3Fg>__ Mani, Inderjeet.

  • 🎓 通过文本分类改进多文档摘要 <https://www.aaai.org/ocs/index.php/AAAI/AAAI17/paper/viewPaper/14525>__ Cao, Ziqiang, et al. (2017).

================================ 文本分类支持

健康医疗

医学领域中的大多数文本信息以非结构化或叙事形式呈现,包含模糊术语和拼写错误。此类信息需要在诊断和治疗的不同阶段的医患诊疗过程中随时可用。医疗编码 (Medical coding),即将医疗诊断分配给从大量类别中获得的具体类值,是文本分类技术可能非常有价值的医疗保健应用领域之一。在其他研究中,J. Zhang 等人引入了 Patient2Vec,以学习纵向电子健康记录 (Electronic Health Record, EHR) 数据的可解释深度表示,该表示针对每位患者个性化。Patient2Vec 是一种新颖的数据集特征嵌入技术,可以基于循环神经网络 (recurrent neural networks) 和注意力机制 (attention mechanism) 学习基于 EHR 数据的个性化可解释深度表示。文本分类也已应用于医学主题词表 (Medical Subject Headings, MeSH) 和基因本体论 (Gene Ontology, GO) 的开发。

  • 🎓 Patient2Vec:纵向电子健康记录的个性化可解释深度表示 <https://ieeexplore.ieee.org/abstract/document/8490816/>__ Zhang, Jinghe, et al. (2018)

  • 🎓 结合贝叶斯文本分类和收缩以自动化医疗编码:数据质量分析 <https://dl.acm.org/citation.cfm?id=2063506>__ Lauría, Eitel JM, and Alan D. March. (2011).

  • 🎓 A <http://b/>__ 等。(2010).

  • 🎓 MeSH Up:有效的 MeSH 文本分类以改善文档检索 <https://academic.oup.com/bioinformatics/article-abstract/25/11/1412/333120>__ Trieschnigg, Dolf, et al.

社会科学

过去几十年,文本分类和文档分类已越来越多地应用于理解人类行为。近年来,人类行为研究中的数据驱动工作侧重于挖掘非正式笔记和文本数据集中的语言,包括短消息服务 (SMS)、临床笔记、社交媒体等。这些研究主要侧重于使用基于单词出现频率的方法(即单词在文档中出现的频率)或基于语言调查词计数 (Linguistic Inquiry Word Count, LIWC) 的特征,LIWC 是一个经过验证的具有心理学相关性的单词类别词典。

  • 🎓 使用短信识别年轻人迫在眉睫的自杀风险 <https://dl.acm.org/citation.cfm?id=3173987>__ Nobles, Alicia L., et al. (2018).

  • 🎓 文本情感分类:跨数据集互操作性研究 <https://link.springer.com/chapter/10.1007/978-3-319-63004-5_21>__ Ofoghi, Bahadorreza, and Karin Verspoor. (2017).

  • 🎓 公共卫生的社会监测 <https://www.morganclaypool.com/doi/abs/10.2200/S00791ED1V01Y201707ICR060>__ Paul, Michael J., and Mark Dredze (2017).

商业与营销

盈利性公司和企业正越来越多地使用社交媒体进行营销目的。从社交媒体(如 Facebook、Twitter 等)中进行意见挖掘 (Opinion mining) 是公司快速增加利润的主要目标。文本和文档分类是公司比以往任何时候都更容易找到客户的强大工具。

  • 🎓 Opinion mining using ensemble text hidden Markov models for text classification <https://www.sciencedirect.com/science/article/pii/S0957417417304979>__ Kang, Mangi, Jaelim Ahn, and Kichun Lee. (2018).

  • 🎓 Classifying business marketing messages on Facebook <https://www.researchgate.net/profile/Bei_Yu2/publication/236246670_Classifying_Business_Marketing_Messages_on_Facebook/links/56bcb34408ae6cc737c6335b.pdf>__ Yu, Bei, and Linchi Kwok.

法律

政府机构已产生海量的法律文本信息及文档。检索这些信息并对其进行自动分类,不仅可以帮助律师,也能惠及他们的客户。 在美国,法律源自五个来源:宪法、成文法、条约、行政法规和普通法。此外,每年都有大量新的法律文件被创建。对这些文件进行分类是法律界面临的主要挑战。

  • 🎓 Represent yourself in court: How to prepare & try a winning case <https://books.google.com/books?hl=en&lr=&id=-lodDQAAQBAJ&oi=fnd&pg=PP1&dq=Represent+yourself+in+court:+How+to+prepare+%5C%26+try+a+winning+case&ots=tgJ8Q2MkH_&sig=9o3ILDn3LfO30BZKsyI2Ou7Q8Qs>__ Bergman, Paul, and Sara J. Berman. (2016)

  • 🎓 Text retrieval in the legal world <https://link.springer.com/article/10.1007/BF00877694>__ Turtle, Howard.

========== 引用:


.. code::

@ARTICLE{Kowsari2018Text_Classification,
    title={Text Classification Algorithms: A Survey},
    author={Kowsari, Kamran and Jafari Meimandi, Kiana and Heidarysafa, Mojtaba and Mendu, Sanjana and Barnes, Laura E. and Brown, Donald E.},
    journal={Information},
    VOLUME = {10},  
    YEAR = {2019},
    NUMBER = {4},
    ARTICLE-NUMBER = {150},
    URL = {http://www.mdpi.com/2078-2489/10/4/150},
    ISSN = {2078-2489},
    publisher={Multidisciplinary Digital Publishing Institute}
}

.. |RMDL| image:: docs/pic/RMDL.jpg .. |line| image:: docs/pic/line.png :alt: 占位符 .. |HDLTex| image:: docs/pic/HDLTex.png

.. |twitter| image:: https://img.shields.io/twitter/url/http/shields.io.svg?style=social :target: https://twitter.com/intent/tweet?text=Text%20Classification%20Algorithms:%20A%20Survey%0aGitHub:&url=https://github.com/kk7nc/Text_Classification&hashtags=Text_Classification,classification,MachineLearning,Categorization,NLP,NATURAL,LANGUAGE,PROCESSING

.. |contributions-welcome| image:: https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat :target: https://github.com/kk7nc/Text_Classification/pulls .. |ansicolortags| image:: https://img.shields.io/pypi/l/ansicolortags.svg :target: https://github.com/kk7nc/Text_Classification/blob/master/LICENSE .. |contributors| image:: https://img.shields.io/github/contributors/kk7nc/Text_Classification.svg :target: https://github.com/kk7nc/Text_Classification/graphs/contributors

.. |arXiv| image:: https://img.shields.io/badge/arXiv-1904.08067-red.svg?style=flat :target: https://arxiv.org/abs/1904.08067

.. |DOI| image:: https://img.shields.io/badge/DOI-10.3390/info10040150-blue.svg?style=flat :target: https://doi.org/10.3390/info10040150

.. |medium| image:: https://img.shields.io/badge/Medium-Text%20Classification-blueviolet.svg :target: https://medium.com/text-classification-algorithms/text-classification-algorithms-a-survey-a215b7ab7e2d

.. |UniversityCube| image:: https://img.shields.io/badge/UniversityCube-Follow%20us%20for%20the%20Latest%20News!-blue.svg :target: https://www.universitycube.net/news

.. |mendeley| image:: https://img.shields.io/badge/Mendeley-Add%20to%20Library-critical.svg :target: https://www.mendeley.com/import/?url=https://doi.org/10.3390/info10040150

.. |Best| image:: https://img.shields.io/badge/Award-Best%20Paper%20Award%202019-brightgreen :target: https://www.mdpi.com/journal/information/awards

.. |BPW| image:: docs/pic/BPW.png :target: https://www.mdpi.com/journal/information/awards

常见问题

相似工具推荐

stable-diffusion-webui

stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。

162.1k|★★★☆☆|今天
开发框架图像Agent

everything-claude-code

everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上

139k|★★☆☆☆|今天
开发框架Agent语言模型

ComfyUI

ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。

107.7k|★★☆☆☆|2天前
开发框架图像Agent

NextChat

NextChat 是一款轻量且极速的 AI 助手,旨在为用户提供流畅、跨平台的大模型交互体验。它完美解决了用户在多设备间切换时难以保持对话连续性,以及面对众多 AI 模型不知如何统一管理的痛点。无论是日常办公、学习辅助还是创意激发,NextChat 都能让用户随时随地通过网页、iOS、Android、Windows、MacOS 或 Linux 端无缝接入智能服务。 这款工具非常适合普通用户、学生、职场人士以及需要私有化部署的企业团队使用。对于开发者而言,它也提供了便捷的自托管方案,支持一键部署到 Vercel 或 Zeabur 等平台。 NextChat 的核心亮点在于其广泛的模型兼容性,原生支持 Claude、DeepSeek、GPT-4 及 Gemini Pro 等主流大模型,让用户在一个界面即可自由切换不同 AI 能力。此外,它还率先支持 MCP(Model Context Protocol)协议,增强了上下文处理能力。针对企业用户,NextChat 提供专业版解决方案,具备品牌定制、细粒度权限控制、内部知识库整合及安全审计等功能,满足公司对数据隐私和个性化管理的高标准要求。

87.6k|★★☆☆☆|今天
开发框架语言模型

ML-For-Beginners

ML-For-Beginners 是由微软推出的一套系统化机器学习入门课程,旨在帮助零基础用户轻松掌握经典机器学习知识。这套课程将学习路径规划为 12 周,包含 26 节精炼课程和 52 道配套测验,内容涵盖从基础概念到实际应用的完整流程,有效解决了初学者面对庞大知识体系时无从下手、缺乏结构化指导的痛点。 无论是希望转型的开发者、需要补充算法背景的研究人员,还是对人工智能充满好奇的普通爱好者,都能从中受益。课程不仅提供了清晰的理论讲解,还强调动手实践,让用户在循序渐进中建立扎实的技能基础。其独特的亮点在于强大的多语言支持,通过自动化机制提供了包括简体中文在内的 50 多种语言版本,极大地降低了全球不同背景用户的学习门槛。此外,项目采用开源协作模式,社区活跃且内容持续更新,确保学习者能获取前沿且准确的技术资讯。如果你正寻找一条清晰、友好且专业的机器学习入门之路,ML-For-Beginners 将是理想的起点。

85k|★★☆☆☆|今天
图像数据工具视频

ragflow

RAGFlow 是一款领先的开源检索增强生成(RAG)引擎,旨在为大语言模型构建更精准、可靠的上下文层。它巧妙地将前沿的 RAG 技术与智能体(Agent)能力相结合,不仅支持从各类文档中高效提取知识,还能让模型基于这些知识进行逻辑推理和任务执行。 在大模型应用中,幻觉问题和知识滞后是常见痛点。RAGFlow 通过深度解析复杂文档结构(如表格、图表及混合排版),显著提升了信息检索的准确度,从而有效减少模型“胡编乱造”的现象,确保回答既有据可依又具备时效性。其内置的智能体机制更进一步,使系统不仅能回答问题,还能自主规划步骤解决复杂问题。 这款工具特别适合开发者、企业技术团队以及 AI 研究人员使用。无论是希望快速搭建私有知识库问答系统,还是致力于探索大模型在垂直领域落地的创新者,都能从中受益。RAGFlow 提供了可视化的工作流编排界面和灵活的 API 接口,既降低了非算法背景用户的上手门槛,也满足了专业开发者对系统深度定制的需求。作为基于 Apache 2.0 协议开源的项目,它正成为连接通用大模型与行业专有知识之间的重要桥梁。

77.1k|★★★☆☆|昨天
Agent图像开发框架