精华内容
下载资源
问答
  • 文本词向量:词集模型、词典模型、TF-IDF1.词集模型2.词袋模型3.词袋模型CountVectorizer实现3.1 词袋化/向量化3.2 使用现有词袋的特征,对其他文本进行特征提取4.TF-IDF4.1 原理4.2 sklearn进行TF-IDF预处理4.3 TF-...


    文本特征提取有两个非常重要的模型:

    • 词集模型:单词构成的集合,集合自然每个元素都只有一个,也即词集中的每个单词都只有一个。

    • 词袋模型:在词集的基础上如果一个单词在文档中出现不止一次,统计其出现的次数(频数)。

    两者本质上的区别:词袋是在词集的基础上增加了频率的维度,词集只关注有和没有,词袋还要关注有几个。

    1.词集模型

    词集模型(Set of Words,简称SoW): 单词构成的集合,每个单词只出现一次。
    它仅仅考虑词是否在文本中出现,而不考虑词频。也就是一个词在文本在文本中出现1次和多次特征处理是一样的。在大多数时候,我们使用词袋模型,后面的讨论也是以词袋模型为主。

    2.词袋模型

    词袋模型(Bag of Words,简称BoW),即将所有词语装进一个袋子里,不考虑其词法和语序的问题,即每个词语都是独立的,把每一个单词都进行统计,同时计算每个单词出现的次数。也就是说,词袋模型不考虑文本中词与词之间的上下文关系,仅仅只考虑所有词的权重,而权重与词在文本中出现的频率有关。

    • 词袋模型会首先进行分词,然后计算每个词(字)在每个文本(句子)中的频数,然后将每个文本中对应的字用相应的频数替代,从而一个文本就可以进行向量化表示,但是基于词袋模型的向量化表示依旧是稀疏的,只是将onehot中的1变成了频数罢了。。

    • 当然,词袋模型有很大的局限性,因为它仅仅考虑了词频,没有考虑上下文的关系,因此会丢失一部分文本的语义。但是大多数时候,如果我们的目的是分类聚类,则词袋模型表现的很好。

    3.词袋模型CountVectorizer实现

    scikit-learn中已经实现了词袋模型的算法,直接用scikit-learnCountVectorizer类来完成,这个类可以帮我们完成文本的词频统计与向量化。
    CountVectorize函数比较重要的几个参数为:

    • decode_error,处理解码失败的方式,分为‘strict’、‘ignore’、‘replace’三种方式。

    • strip_accents,在预处理步骤中移除重音的方式。默认为None,可设为ascii或unicode,将使用ascii或unicode编码在预处理步骤去除raw document中的重音符号。

    • max_features,词袋特征个数的最大值。

    • stop_words,设置停用词,设为english将使用内置的英语停用词,设为一个list可自定义停用词,设为None不使用停用词,设为None且max_df∈[0.7, 1.0)将自动根据当前的语料库建立停用词表。

    • max_df,可以设置为范围在[0.0 1.0]的float,也可以设置为没有范围限制的int,默认为1.0。这个参数的作用是作为一个阈值,当构造语料库的关键词集的时候,如果某个词的document frequence大于max_df,这个词不会被当作关键词。如果这个参数是float,则表示词出现的次数与语料库文档数的百分比,如果是int,则表示词出现的次数。如果参数中已经给定了vocabulary,则这个参数无效。

    • min_df,类似于max_df,参数min_df=n表示词必须要在至少n个文档中出现过,否则就不考虑。

    • binary,默认为False,当与TF-IDF结合使用时需要设置为True。

    CountVectorizer是通过fit_transform()函数将文本中的词语转换为词频矩阵,矩阵元素a[i][j] 表示j词在第i个文本下的词频。即各个词语出现的次数,通过get_feature_names()可看到所有文本的关键字,通过toarray()可看到词频矩阵的结果。

    3.1 词袋化/向量化

    from sklearn.feature_extraction.text import CountVectorizer
     
    # 实例化分词对象
    vec = CountVectorizer(min_df=1)
     
    # 将文本进行词袋处理
    corpus = ['This is the first document.',
            'This is the second second document.',
            'And the third one.',
            'Is this the first document?']
     
    X = vec.fit_transform(corpus)
    print(X)
    

    输出为:

      (0, 2)    1
      (0, 3)    1
      (0, 6)    1
      (0, 4)    1
      (0, 7)    1
      (1, 5)    2
      (1, 2)    1
      (1, 6)    1
      (1, 4)    1
      (1, 7)    1
      (2, 9)    1
      (2, 0)    1
      (2, 8)    2
      (2, 1)    1
      (3, 2)    1
      (3, 3)    1
      (3, 6)    1
      (3, 4)    1
      (3, 7)    1
    

    其中,括号中的第一个数字是文本的序号,第2个数字是词的序号,注意词的序号是基于所有的文档的。第三个数字就是我们的词频。
    (1) 使用 get_feature_names 可以得到列名,也就是分词后得到的set

    fnames = vec.get_feature_names()
    print(fnames)
    

    输出为:

    ['china', 'come', 'document', 'first', 'is', 'second', 'the', 'this', 'to', 'travel']
    

    (2)获取每个文本的向量矩阵

    arr = X.toarray()
    print(arr)
    

    输出为:

    [[0 0 1 1 1 0 1 1 0 0]
     [0 0 1 0 1 2 1 1 0 0]
     [1 1 0 0 0 0 0 0 2 1]
     [0 0 1 1 1 0 1 1 0 0]]
    

    可以看到一共有10个词,所以4个文本都是10维的特征向量。而每一维的向量依次对应了上面的10个词。另外由于词"I"在英文中是停用词,不参加词频的统计。

    由于大部分的文本都只会使用词汇表中的很少一部分的词,因此词向量中会有大量的0。也就是说词向量是稀疏的。
    (3) 缺点:

    向量化的方法很好用,也很直接,但是在有些场景下很难使用,比如分词后的词汇表非常大,以至于 维度爆照,甚至达到100万+,此时如果我们直接使用向量化的方法,将对应的样本对应特征矩阵载入内存,有可能将内存撑爆

    3.2 使用现有词袋的特征,对其他文本进行特征提取

    如何可以使用现有的词袋的特征,对其他文本进行特征提取呢?

    我们定义词袋的特征空间叫做词汇表vocabulary:vocabulary=vec.vocabulary_

    对其他文本进行词袋处理时,可以直接使用现有的词汇表:

    vocabulary=vec.vocabulary_
    new_vectorizer = CountVectorizer(min_df=1, vocabulary=vocabulary)
    corpus2=["I come to China to travel",
        "This is a car polupar in China",
        "I love tea and Apple ",
        "The work is to write some papers in science"]
     
    arr2 = new_vectorizer.fit_transform(corpus2).toarray()
    print(arr2)
     
    fnames2 = vec.get_feature_names()
    print(fnames2)
    

    输出为:

    [[1 1 0 0 0 0 0 0 2 1]
     [1 0 0 0 1 0 0 1 0 0]
     [0 0 0 0 0 0 0 0 0 0]
     [0 0 0 0 1 0 1 0 1 0]]
    ['china', 'come', 'document', 'first', 'is', 'second', 'the', 'this', 'to', 'travel']
    

    4.TF-IDF

    在词袋模型中引用词频来表示词向量,但是词频多的词不一定是最重要的,一个词出现在不同的文本中的次数越多,那么这个词就越不重要,所以基于这个逻辑,提出了tf-idf,其中tf就是在文本中出现的词频,idf相当于词的重要性权重,进行特征的权重修正。

    4.1 原理

    TF-IDF(Term Frequency–Inverse Document Frequency),即“词频-逆文本频率”,是一种用于资讯检索与文本挖掘的常用加权技术。它由两部分组成,TF和IDF。

    TF-IDF是一种统计方法,用以评估一个字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。TF-IDF加权的各种形式常被搜索引擎应用,作为文件与用户查询之间相关程度的度量或评级。

    TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。TF-IDF实际上是:TF * IDF。

    (1).词频(Term Frequency,TF):指的是某一个给定的词语在该文件中出现的频率。

    (2).逆向文件频率(Inverse Document Frequency,IDF):是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。

    • IDF反应了一个词在所有文本中出现的频率,如果一个词在很多的文本中出现,那么它的IDF值应该低,比如“to”;反过来,如果一个词在比较少的文本中出现,那么它的IDF值应该高。比如一些专业的名词如“Machine Learning”。一个极端的情况,如果一个词在所有的文本中都出现,那么它的IDF值应该为0。公式如下:
      IDF(x)=logNN(x) IDF(x) = log{\frac{N}{N(x)}}

      其中,N代表语料库中文本的总数,而N(x)代表语料库中包含词x的文本总数。

    • 上面的IDF公式已经可以使用了,但是在一些特殊的情况会有一些小问题,比如某一个生僻词在语料库中没有,这样分母为0, IDF没有意义了。所以常用的IDF需要做一些平滑,使语料库中没有出现的词也可以得到一个合适的IDF值。平滑的方法有很多种,最常见的IDF平滑公式之一为:

    IDF(x)=logN+1N(x)+1+1 IDF(x) = log{\frac{N+1}{N(x)+1}+1}

    • 某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语
      TFIDF(x)=TF(x)IDF(x) TF-IDF(x) = TF(x) \ast IDF(x)

    4.2 sklearn进行TF-IDF预处理

    (1)CountVectorizer 结合 TfidfTransformer

    from sklearn.feature_extraction.text import TfidfTransformer
    from sklearn.feature_extraction.text import CountVectorizer
     
    corpus = ['This is the first document.',
              'This is the second second document.',
              'And the third one.',
              'Is this the first document?',
              ]
     
    # 词袋化
    vectorizer = CountVectorizer()
    X = vectorizer.fit_transform(corpus)
    print(X)
     
    # TF-IDF
    transformer = TfidfTransformer()
    tfidf = transformer.fit_transform(X)
    print(tfidf)
    

    词袋化结果:

      (0, 1)    1
      (0, 2)    1
      (0, 6)    1
      (0, 3)    1
      (0, 8)    1
      (1, 5)    2
      (1, 1)    1
      (1, 6)    1
      (1, 3)    1
      (1, 8)    1
      (2, 4)    1
      (2, 7)    1
      (2, 0)    1
      (2, 6)    1
      (3, 1)    1
      (3, 2)    1
      (3, 6)    1
      (3, 3)    1
      (3, 8)    1
    

    输出的各个文本各个词的 TF-IDF 值如下:

      (0, 8)    0.4387767428592343
      (0, 3)    0.4387767428592343
      (0, 6)    0.35872873824808993
      (0, 2)    0.5419765697264572
      (0, 1)    0.4387767428592343
      (1, 8)    0.27230146752334033
      (1, 3)    0.27230146752334033
      (1, 6)    0.2226242923251039
      (1, 1)    0.27230146752334033
      (1, 5)    0.8532257361452784
      (2, 6)    0.2884767487500274
      (2, 0)    0.5528053199908667
      (2, 7)    0.5528053199908667
      (2, 4)    0.5528053199908667
      (3, 8)    0.4387767428592343
      (3, 3)    0.4387767428592343
      (3, 6)    0.35872873824808993
      (3, 2)    0.5419765697264572
      (3, 1)    0.4387767428592343
    

    (2)用 TfidfVectorizer

    from sklearn.feature_extraction.text import TfidfVectorizer
     
    tfidf2 = TfidfVectorizer()
    corpus = ['This is the first document.',
              'This is the second second document.',
              'And the third one.',
              'Is this the first document?',
              ]
     
    re = tfidf2.fit_transform(corpus)
    print(re)
    
      (0, 8)    0.4387767428592343
      (0, 3)    0.4387767428592343
      (0, 6)    0.35872873824808993
      (0, 2)    0.5419765697264572
      (0, 1)    0.4387767428592343
      (1, 8)    0.27230146752334033
      (1, 3)    0.27230146752334033
      (1, 6)    0.2226242923251039
      (1, 1)    0.27230146752334033
      (1, 5)    0.8532257361452784
      (2, 6)    0.2884767487500274
      (2, 0)    0.5528053199908667
      (2, 7)    0.5528053199908667
      (2, 4)    0.5528053199908667
      (3, 8)    0.4387767428592343
      (3, 3)    0.4387767428592343
      (3, 6)    0.35872873824808993
      (3, 2)    0.5419765697264572
      (3, 1)    0.4387767428592343
    

    4.3 TF-IDF小结:

    无论是词集模型、词袋模型还是TF-IDF,都是从词频的方面去考虑词向量,所成向量维度依旧巨大,而且稀疏,最关键的是这三个模型都学习不到字词的相似关系,因为这三个模型出来的词向量都是稀疏的,随便取2个字词作余弦相似度都=0,这是不合理的。因此提出word2vec,通过上下文的关系来学习词向量,便于学习字词相似度,当然如果是单纯作分类/聚类操作的时候,TF-IDF更加方便。

    展开全文
  • 浅谈文本词向量转换的机制embedding

    千次阅读 2018-03-12 18:37:52
    首先感谢大家对上一篇...上文说道关于文本词向量转换的embedding相关的内容,其实是没有详细说明的,那这一篇我尝试着去解释一些,说的不对的还望各位大神指正,我也是自学的,没人一起讨论,可能有理解不到位的地方。

    首先感谢大家对上一篇文章的关注吧,建议看这篇文章前先看下上一篇我推送的《20行代码实现电影评论情感分析》,上篇文章其实留了个坑,不过不一定坑到大家,因为可能90%的同学可能不会去认真读一遍代码,或者去跑一下程序。上文说道关于文本词向量转换的embedding相关的内容,其实是没有详细说明的,那这一篇我尝试着去解释一些,说的不对的还望各位大神指正,我也是自学的,没人一起讨论,可能有理解不到位的地方。


    其实机器学习算法,无非是矩阵的加减乘除,对于文本string型的数据,必然需要把这类数据转成数值型的向量,才能方便计算。文本转词向量就是起到这样的作用,当然,方法有很多,这里我们提到的机制有点类似于算法word2vector,它会把文本转成带有语意的向量。


    什么是带有语意的向量?就拿上一篇推送里出现的tflearn.embedding它起到的作用说起。它其实是通过大量的语句分析挖掘出词语之间的相似度,举个简单的例子,假设有大量的语句中都出现“美女喜欢帅哥”、“美女喜欢好看的男人”,那么算法会挖掘出“帅哥”和“好看的男人”可能是相似的语意,于是可以通过向量表示,以下向量纯属yy,为了举例:

    美女=[3,5,7]

    帅哥=[5,3,9]

    好看的男人=[5.1,2.9,9]


    “帅哥”和“好看的男人”会被用距离更近的向量表示起来。另外,向量间的距离也可能会建立联系,比方说“北京”是“中国”的首都,“巴黎”是“法国”的首都,那么向量:|中国|-|北京|=|法国|-|巴黎|


    通过embedding函数把所有词向量距离计算出来后,其实每句话就可以通过词向量组装成矩阵,简单的方式是第一行是第一个词向量,第二行是第二个。那么两句话的语意相似度就可以通过简单的矩阵减法计算啦,感谢收看。


    上一篇《20行代码实现电影评论情感分析》代码地址,我只放了一点点测试数据,完整的数据大家自己去IMDB下吧:https://github.com/jimenbian/sentiment-analysis

    展开全文
  • 写在前面:笔者最近在梳理自己的文本挖掘知识结构,借助gensim、sklearn、keras等库的文档做了些扩充,会陆陆续续介绍文本向量化、tfidf、主题模型、word2vec,既会涉及理论,也会有详细的代码和案例进行讲解,希望...

    写在前面:笔者最近在梳理自己的文本挖掘知识结构,借助gensim、sklearn、keras等库的文档做了些扩充,会陆陆续续介绍文本向量化、tfidf、主题模型、word2vec,既会涉及理论,也会有详细的代码和案例进行讲解,希望在梳理自身知识体系的同时也能对想学习文本挖掘的朋友有一点帮助,这是笔者写该系列的初衷。

    在本文中,笔者将会紧接着上文提及的3个概念,拓展到文本挖掘中一个重要的概念 ---(文本)向量空间,它是将自然语言转化为机器可识别符号的关键一步,文本相似度、文本聚类、文本分类等实际应用皆以此为基础。

    培养码代码的好习惯,设置日志,打印程序运行中的细节,以便调试代码。

    import logginglogging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
    import osimport tempfileTEMP_FOLDER = tempfile.gettempdir()print('文件夹"{}" 将被用来存储语料和临时性的字典'.format(TEMP_FOLDER))
    文件夹"C:\Users\hp\AppData\Local\Temp" 将被用来存储语料和临时性的字典

    一、从字符串到向量(From Strings to Vectors)

    这次,笔者还是使用之前关于“知识图谱”报道的标题语料库作为示例:

    from gensim import corporaimport jieba

    2019-05-06 09:59:43,964 : INFO : 'pattern' package not found; tag filters are not available for English

    根据打印出的日志可知,'pattern'没正确安装上,这个库是自然语言处理里一个很棒的库,不过目前没怎么更新了,且对中文的支持不给力,所以不影响接下来的分析。

    jieba.add_word('知识图谱') #防止“知识图谱”被切错词docs = ['商业新知:知识图谱为内核,构建商业创新服务完整生态。','如何更好利用知识图谱技术做反欺诈? 360金融首席数据科学家沈赟开讲。','知识管理 | 基于知识图谱的国际知识管理领域可视化分析。','一文详解达观数据知识图谱技术与应用。','知识图谱技术落地金融行业的关键四步。','一文读懂知识图谱的商业应用进程及技术背景。','海云数据CPO王斌:打造大数据可视分析与AI应用的高科技企业。','智能产业|《人工智能标准化白皮书2018》带来创新创业新技术标准。','国家语委重大科研项目“中华经典诗词知识图谱构建技术研究”开题。','最全知识图谱介绍:关键技术、开放数据集、应用案例汇总。','中译语通Jove Mind知识图谱平台 引领企业智能化发展。','知识图谱:知识图谱赋能企业数字化转型,为企业升级转型注入新能量。']

    再对文本进行分词,用空格隔开变成字符串,方便进行下一步的处理:

    documents = [' '.join(jieba.lcut(i)) for i in docs]documents 

    ['商业 新知 : 知识图谱 为 内核 , 构建 商业 创新 服务 完整 生态 。',
    '如何 更好 利用 知识图谱 技术 做 反 欺诈 ? 360 金融 首席 数据 科学家 沈赟 开讲 。',
    '知识 管理 | 基于 知识图谱 的 国际 知识 管理 领域 可视化 分析 。',
    '一文 详解 达观 数据 知识图谱 技术 与 应用 。',
    '知识图谱 技术 落地 金融 行业 的 关键 四步 。',
    '一文 读懂 知识图谱 的 商业 应用 进程 及 技术 背景 。',
    '海云 数据 CPO 王斌 : 打造 大 数据 可视 分析 与 AI 应用 的 高科技 企业 。',
    '智能 产业 | 《 人工智能 标准化 白皮书 2018 》 带来 创新 创业 新 技术标准 。',
    '国家语委 重大 科研项目 “ 中华 经典 诗词 知识图谱 构建 技术 研究 ” 开题 。',
    '最全 知识图谱 介绍 : 关键技术 、 开放 数据 集 、 应用 案例 汇总 。',
    '中译 语通 Jove Mind 知识图谱 平台 引领 企业 智能化 发展 。',
    '知识图谱 : 知识图谱 赋能 企业 数字化 转型 , 为 企业 升级 转型 注入 新 能量 。']

    这是一个包含12个文档的小型语料,每个文档仅包含1个语句。

    首先,对这些文档进行分词处理,移除停用词,并去掉那些仅在本语料中出现一次的词汇:

    # 移除常用词以及分词stoplist = [i.strip() for i in open('datasets/stopwords_zh.txt',encoding='utf-8').readlines()]texts = [[word for word in document.lower().split() if word not in stoplist]for document in documents]# 移除仅出现一次的词汇from collections import defaultdictfrequency = defaultdict(int)for text in texts:for token in text:        frequency[token] += 1texts = [[token for token in text if frequency[token] > 1] for text in texts]from pprint import pprint  #使打印的格式更齐整pprint(texts)

    [['商业', '知识图谱', '商业', '创新'],
    ['知识图谱', '技术', '金融', '数据'],
    ['知识', '管理', '知识图谱', '知识', '管理', '分析'],
    ['一文', '数据', '知识图谱', '技术'],
    ['知识图谱', '技术', '金融'],
    ['一文', '知识图谱', '商业', '技术'],
    ['数据', '数据', '分析', '企业'],
    ['创新'],
    ['知识图谱', '技术'],
    ['知识图谱', '数据'],
    ['知识图谱', '企业'],
    ['知识图谱', '知识图谱', '企业', '转型', '企业', '转型']]

    处理文档的方式需要因时制宜,随机应变,尤其是在不同的应用场景中,比如电商评论、博客长文以及微博内容都需要使用不同的预处理方法,笔者会在后面的文章中提及这些技巧。在这里,基于上面的分词,笔者仅用空格分开,然后对语句中的西文词汇进行“小写化(Lowercasing)”。 

    机器是看不懂人类的自然语言(自然语言通常是指一种自然地随文化演化的语言。例如,英语、汉语、日语为自然语言的例子,而世界语则为人造语言,即是一种为某些特定目的而创造的语言),若要机器“读懂”自然语言,则需要将其转换为机器可识别的符号,比如"0"和"1",且这种转换的过程中需要最大限度保留自然语言特有的语义特征,这是一个很有难度的任务。在这里,笔者介绍一种常见的文本表示方法 --- 称为词袋模型,即Bag-of-Words)。

    词袋模型模型下,像是句子或是文件这样的文字可以用一个袋子装着这些词的方式表现,这种表现方式不考虑文法以及词的顺序。https://baike.baidu.com/item/%E8%AF%8D%E8%A2%8B%E6%A8%A1%E5%9E%8B/22776998?fr=aladdin

    后面还会有很多不同的文本表示方法,比如TF-IDF、LSA、LSI、LDA、HDP、NMF、Word2vec等。但是,请记住,不同的应用场景需要不同的文本特征,没有百试不爽的方法,并且,请一如既往的记住这句名言:

    垃圾入,垃圾出(garbage in, garbage out)

    使用词袋模型将多个文档转换为向量,每个文档由一个向量表示,其中向量元素“i”表示第i个单词出现在文档中的次数。

    仅通过它们的(整型)id来表征词汇是有利的, 问题和ID之间的映射称为字典(dictionary)

    dictionary = corpora.Dictionary(texts)dictionary.save(os.path.join(TEMP_FOLDER, 'deerwester.dict'))  # 保存字典,以备后续查找之用print(dictionary)
    2019-05-06 15:58:09,861 : INFO : adding document #0 to Dictionary(0 unique tokens: [])
    2019-05-06 15:58:09,867 : INFO : built Dictionary(12 unique tokens: ['创新', '商业', '知识图谱', '技术', '数据']...) from 12 documents (total 42 corpus positions)
    2019-05-06 15:58:09,873 : INFO : saving Dictionary object under C:\Users\hp\AppData\Local\Temp\deerwester.dict, separately None
    2019-05-06 15:58:09,879 : INFO : saved C:\Users\hp\AppData\Local\Temp\deerwester.dict
    Dictionary(12 unique tokens: ['创新', '商业', '知识图谱', '技术', '数据']...)

    在这里,我们通过gensim.corpora.dictionary.Dictionary这个类为处理过的语料库中出现的每个词汇分配一个独一无二的整数ID 。 这会扫描整个文本,统计所有的词汇计数和词汇相关数据。 最后,我们看到在处理的语料库中有12个不同的词汇,这意味着每个文档将由12个数字表示(即12-D向量)。 下面,查看每个词汇与其对应ID之间的映射关系:

    print(dictionary.token2id)
    {'创新': 0, '商业': 1, '知识图谱': 2, '技术': 3, '数据': 4, '金融': 5, '分析': 6, '知识': 7, '管理': 8, '一文': 9, '企业': 10, '转型': 11}

    将分词后的文档实际转换为向量:

    new_doc = "知识图谱 为 企业 转型 助力"new_vec = dictionary.doc2bow(new_doc.lower().split())print(new_vec)  # “为”、“助力”等词汇未出现在字典中,因而被忽略
    [(2, 1), (10, 1), (11, 1)]

    函数doc2bow()只是计算每个不同词汇的出现次数,将词汇转换为整数词汇id,并将结果作为一个词袋(bag-of-words)--- 一个稀疏向量返回,形式为( word_id1,word_count1),( word_id2,word_count2),( word_id3,word_count3)...

    在token_id中,“创新”对应的为0,“商业”为1,...,'转型'为11。因而,新文档“知识图谱 为 企业 转型 助力(知识图谱为企业转型助力)”将被转换为[(2, 1), (10, 1), (11, 1)]。 "知识图谱"、“企业”、“转型” 出现在词典中并出现一次。 因此,它们在稀疏向量中分别变为(2, 1), (10, 1), (11, 1)。 “为”、“转型”、“助力”等词汇在字典中不存在,因此不会出现在稀疏向量中。 词汇计数为0的词汇不会出现在稀疏向量中,并且稀疏向量中将永远不会出现像(3,0)这样的元素。

    对于熟悉scikit-learn的人来说,doc2bow()与在CountVectorizer上调用transform()有类似的作用(http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.CountVectorizer.html)。 doc2bow()也可以像fit_transform()那样运作,相关详细信息,请参阅gensim API Doc(https://radimrehurek.com/gensim/corpora/dictionary.html#gensim.corpora.dictionary.Dictionary.doc2bow)。

    corpus = [dictionary.doc2bow(text) for text in texts]corpora.MmCorpus.serialize(os.path.join(TEMP_FOLDER, 'deerwester.mm'), corpus)  #保存到本地,以作后用for c in corpus:print(c)
    2019-05-06 16:00:28,683 : INFO : storing corpus in Matrix Market format to C:\Users\hp\AppData\Local\Temp\deerwester.mm
    2019-05-06 16:00:28,688 : INFO : saving sparse matrix to C:\Users\hp\AppData\Local\Temp\deerwester.mm
    2019-05-06 16:00:28,690 : INFO : PROGRESS: saving document #0
    2019-05-06 16:00:28,693 : INFO : saved 12x12 matrix, density=24.306% (35/144)
    2019-05-06 16:00:28,695 : INFO : saving MmCorpus index to C:\Users\hp\AppData\Local\Temp\deerwester.mm.index

    [(0, 1), (1, 2), (2, 1)]
    [(2, 1), (3, 1), (4, 1), (5, 1)]
    [(2, 1), (6, 1), (7, 2), (8, 2)]
    [(2, 1), (3, 1), (4, 1), (9, 1)]
    [(2, 1), (3, 1), (5, 1)]
    [(1, 1), (2, 1), (3, 1), (9, 1)]
    [(4, 2), (6, 1), (10, 1)]
    [(0, 1)]
    [(2, 1), (3, 1)]
    [(2, 1), (4, 1)]
    [(2, 1), (10, 1)]
    [(2, 2), (10, 2), (11, 2)]

    到目前为止,应该清楚的是,带有id = 10的向量特征表示文档中出现“企业”一词的次数---在这12个文档中, 只有倒数前2个和和倒数第6个的值为1,其他皆为0。

    二、语料库(Corpus Streaming) --- 每次仅调用一个文档

    请注意,上面的语料(corpus)完全驻留在内存中,作为普通的Python列表而存在。 在这个简单的例子中,它并不重要,只是为了阐述方便。让我们假想,手头的语料库中有数千万个文档,要将所有这些文档都存储在RAM中是行不通的,这会消耗大量的计算资源,速度奇慢! 相反,我们假设文档存储在本地的单个文件中,每行一个文档。 Gensim只要求语料库在需要使用时,能够一次返回一个文档向量:

    from smart_open import smart_openclass MyCorpus(object):def __iter__(self):for line in smart_open('datasets/mycorpus.txt', 'r',encoding='utf-8'):# 假设每一行一个文档,用jieba进行分词yield dictionary.doc2bow(' '.join(jieba.lcut(line)).lower().split())

    每个文档占用单个文件中一行的假设并不重要; 你可以设计__iter__函数以适合你的特定输入格式,比如文档目录、待解析的XML、可访问的网络节点...只需解析你的输入以检索每个文档中的所用词汇,然后通过字典将这些词汇转换为它们对应的整数ID,并在__iter__中产生具有生成器属性的稀疏向量。

    corpus_memory_friendly = MyCorpus()  #不需要将语料载入到内存中!print(corpus_memory_friendly)
    <__main__.mycorpus object at>

    现在,corpus_memory_friendly是一个对象。 我们没有定义任何打印(print)方式,因此print只输出对象在内存中的地址, 这看起来没啥用。 要查看其中的向量构成,需要遍历语料库,并打印每个文档向量(一次一个):

    for vector in corpus_memory_friendly:  #每次载入一个文档向量print(vector)
    [(0, 1), (1, 2), (2, 1), (3, 1)]
    [(2, 1), (3, 1), (4, 1), (5, 1), (6, 1)]
    [(2, 1), (3, 3), (7, 1), (8, 2)]
    [(2, 1), (3, 1), (4, 1), (5, 1), (9, 1)]
    [(2, 1), (3, 1), (4, 1), (6, 1)]
    [(1, 1), (2, 1), (3, 1), (4, 1), (9, 1)]
    [(5, 2), (7, 1), (10, 1)]
    [(0, 1)]
    [(2, 1), (3, 1), (4, 1)]
    [(2, 1), (3, 1), (5, 1)]
    [(2, 1), (3, 1), (10, 1)]
    [(2, 2), (3, 2), (10, 1)]

    尽管输出与普通的Python列表的输出相同,但此时的语料库对内存更友好 --- 一次最多只有一个向量驻留在RAM中, 现在,你的语料库想用多大就用多大,哪怕是成千上万个文档,只是速度稍慢罢了。

    我们将使用mycorpus.txt这个文件来创建字典(Dictionary),但不是将整个文件加载到本地内存中。 然后,我们将过滤掉语料中的停用词以及词频为1的词汇,从而得到“净化”后的语料。

    请记住,dictionary.filter_tokens(或者dictionary.add_document)将调用dictionary.compactify()来删除词汇id序列中的间隙,空置的占位符("")将会被剔除。

    from six import iteritemsfrom smart_open import smart_open#收集所有词汇的统计信息dictionary = corpora.Dictionary(' '.join(jieba.lcut(line)).lower().split() for line in smart_open('datasets/mycorpus.txt''r',encoding='utf-8'))#停用词和低频词(这里指仅出现1次的词汇)的ID集合stop_ids = [dictionary.token2id[stopword] for stopword in stoplist if stopword in dictionary.token2id]once_ids = [tokenid for tokenid, docfreq in iteritems(dictionary.dfs) if docfreq == 1]#真正实施去停用词和低频次的操作dictionary.filter_tokens(stop_ids + once_ids)print(dictionary)
    2019-05-06 15:44:52,297 : INFO : adding document #0 to Dictionary(0 unique tokens: [])
    2019-05-06 15:44:52,303 : INFO : built Dictionary(100 unique tokens: [',', ':', '。', '为', '内核']...) from 12 documents (total 164 corpus positions)

    Dictionary(10 unique tokens: ['创新', '商业', '图谱', '知识', '技术']...)

    到这里,词袋表示(Bag-of-words Representation)的原理和操作就说完了。 当然,我们用这种语料库可以做什么是另一个问题; 计算不同单词的出现频率可能是有用的,但在实际场景中,这还不够。

     事实证明,我们经常需要对这个简单的表示进行转换(Transformation),之后才能进行文档相似度、文本聚类或者文本分类这样的任务。 转换后面会提到,但在此之前,让我们将注意力集中在语料库持久性(Corpus Persistency)

    三、语料格式(Corpus Formats)

    存在几种用于将向量空间(Vector Space)语料库(向量序列)序列化到本地的文件格式。 Gensim通过前面提到的流式语料库接口(Streaming Corpus Interface)实现:以惰性方式(A Lazy Fashion)从本地读取大量语料,一次一个文档,而不是一次性将整个语料库读入本地内存中,这在语料库极为庞大时是很折腾电脑的。

    其中,一种比较值得注意的文件格式是Matrix Market格式(http://math.nist.gov/MatrixMarket/formats.html)。 

    下面,将文档以Matrix Market格式保存:

    #创建一个包含2个文档的微小语料,以一个python列表呈现corpus = [[(1, 0.5)], []]  # 其中一个文档故意搞成空的corpora.MmCorpus.serialize(os.path.join(TEMP_FOLDER, 'corpus.mm'), corpus)
    2019-05-06 16:36:54,265 : INFO : storing corpus in Matrix Market format to C:\Users\hp\AppData\Local\Temp\corpus.mm
    2019-05-06 16:36:54,281 : INFO : saving sparse matrix to C:\Users\hp\AppData\Local\Temp\corpus.mm
    2019-05-06 16:36:54,285 : INFO : PROGRESS: saving document #0
    2019-05-06 16:36:54,290 : INFO : saved 2x2 matrix, density=25.000% (1/4)
    2019-05-06 16:36:54,293 : INFO : saving MmCorpus index to C:\Users\hp\AppData\Local\Temp\corpus.mm.index

    其他的存储格式还有Joachim’s SVMlight format(http://svmlight.joachims.org/)、 Blei’s LDA-C format(http://www.cs.columbia.edu/~blei/lda-c/) 和 GibbsLDA++ format(http://gibbslda.sourceforge.net/)。

    corpora.SvmLightCorpus.serialize(os.path.join(TEMP_FOLDER, 'corpus.svmlight'), corpus)corpora.BleiCorpus.serialize(os.path.join(TEMP_FOLDER, 'corpus.lda-c'), corpus)corpora.LowCorpus.serialize(os.path.join(TEMP_FOLDER, 'corpus.low'), corpus)
    2019-05-06 16:39:11,653 : INFO : converting corpus to SVMlight format: C:\Users\hp\AppData\Local\Temp\corpus.svmlight
    2019-05-06 16:39:11,659 : INFO : saving SvmLightCorpus index to C:\Users\hp\AppData\Local\Temp\corpus.svmlight.index
    2019-05-06 16:39:11,662 : INFO : no word id mapping provided; initializing from corpus
    2019-05-06 16:39:11,666 : INFO : storing corpus in Blei's LDA-C format into C:\Users\hp\AppData\Local\Temp\corpus.lda-c
    2019-05-06 16:39:11,671 : INFO : saving vocabulary of 2 words to C:\Users\hp\AppData\Local\Temp\corpus.lda-c.vocab
    2019-05-06 16:39:11,676 : INFO : saving BleiCorpus index to C:\Users\hp\AppData\Local\Temp\corpus.lda-c.index
    2019-05-06 16:39:11,681 : INFO : no word id mapping provided; initializing from corpus
    2019-05-06 16:39:11,684 : INFO : storing corpus in List-Of-Words format into C:\Users\hp\AppData\Local\Temp\corpus.low
    2019-05-06 16:39:11,690 : WARNING : List-of-words format can only save vectors with integer elements; 1 float entries were truncated to integer value
    2019-05-06 16:39:11,693 : INFO : saving LowCorpus index to C:\Users\hp\AppData\Local\Temp\corpus.low.index

    反向操作,从Matrix Market文件加载语料库迭代器(Corpus Iterator)

    corpus = corpora.MmCorpus(os.path.join(TEMP_FOLDER, 'corpus.mm'))
    2019-05-06 16:40:06,275 : INFO : loaded corpus index from C:\Users\hp\AppData\Local\Temp\corpus.mm.index
    2019-05-06 16:40:06,278 : INFO : initializing cython corpus reader from C:\Users\hp\AppData\Local\Temp\corpus.mm
    2019-05-06 16:40:06,281 : INFO : accepted corpus with 2 documents, 2 features, 1 non-zero entries

    语料库对象是流式的(Streams),因此,我们通常无法直接打印它们,只有通过遍历才能看到其中的元素:

    print(corpus)

    MmCorpus(2 documents, 2 features, 1 non-zero entries)

    通过迭代器列表化来查看语料库中的元素:

    # 一种打印语料库的方式是 --- 将其整个载入内存中print(list(corpus))  #  调用 list() 能将任何序列转化为普通的Python list

    [[(1, 0.5)], []]

    或者这样:

    # 另一种方法:一次打印一个文档for doc in corpus:print(doc)
    [(1, 0.5)]
    []

    显然,第二种方式对内存更友好,但是出于测试和开发的目的,没有什么比调用list(corpus)更简单、快捷!。

    接下来,以Blei的LDA-C格式保存相同的Matrix Market文档流:

    corpora.BleiCorpus.serialize(os.path.join(TEMP_FOLDER, 'corpus.lda-c'), corpus)
    2019-05-06 16:46:55,322 : INFO : no word id mapping provided; initializing from corpus
    2019-05-06 16:46:55,325 : INFO : storing corpus in Blei's LDA-C format into C:\Users\hp\AppData\Local\Temp\corpus.lda-c
    2019-05-06 16:46:55,329 : INFO : saving vocabulary of 2 words to C:\Users\hp\AppData\Local\Temp\corpus.lda-c.vocab
    2019-05-06 16:46:55,332 : INFO : saving BleiCorpus index to C:\Users\hp\AppData\Local\Temp\corpus.lda-c.index

    通过这种方式,gensim也可以用作内存高效的I / O格式转换工具:只需使用一种格式加载文档流,然后立即以另一种格式进行保存。 

    四、与NumPy、SciPy的兼容性

    Gensim还囊括许多高效且实用的函数,可以在(http://radimrehurek.com/gensim/matutils.html) 看到,通过这些函数,我们可以轻松的进行numpy矩阵的转换:

    import gensimimport numpy as npnumpy_matrix = np.random.randint(10, size=[5,2])
    numpy_matrix
    array([[0, 4],
    [0, 7],
    [8, 2],
    [7, 0],
    [2, 1]])
    corpus = gensim.matutils.Dense2Corpus(numpy_matrix)numpy_matrix_dense = gensim.matutils.corpus2dense(corpus, num_terms=10)
    D:\anaconda20190415\lib\site-packages\gensim\matutils.py:503: FutureWarning: arrays to stack must be passed as a "sequence" type such as list or tuple. Support for non-sequence iterables such as generators is deprecated as of NumPy 1.16 and will raise an error in the future.
    result = np.column_stack(sparse2full(doc, num_terms) for doc in corpus)
    numpy_matrix_dense
    array([[0., 4.],
    [0., 7.],
    [8., 2.],
    [7., 0.],
    [2., 1.],
    [0., 0.],
    [0., 0.],
    [0., 0.],
    [0., 0.],
    [0., 0.]], dtype=float32)

    scipy.sparse矩阵相互转换:

    import scipy.sparsescipy_sparse_matrix = scipy.sparse.random(5,2)
    scipy_sparse_matrix
    <5x2 sparse matrix of type ''
    with 0 stored elements in COOrdinate format>
    corpus = gensim.matutils.Sparse2Corpus(scipy_sparse_matrix)
    corpus
    scipy_csc_matrix = gensim.matutils.corpus2csc(corpus)
    scipy_csc_matrix
    <0x2 sparse matrix of type ''
    with 0 stored elements in Compressed Sparse Column format>

    要获得完整的参考(想要将字典的规模精简下以节约内存?优化语料库和NumPy / SciPy数组之间的转换?),请参阅gensim的API文档。

     在下一篇文章中,笔者会接着本次的主题,说说关于主题模型和文本数据转换,即TF-IDF模型、潜在语义索引(LSI)、随机映射(Random Projections)、隐狄利克雷分配模型(Latent Dirichlet Allocation, LDA)、层次狄利克雷过程(Hierarchical Dirichlet Process,HDP)的教程。

    注:以上内容大部分来自gensim的英文文档,笔者只是用中文语料进行了新的诠释,后续还会有更多的内容,笔者将不定期更新,动力来自于读者的热情,想让笔者持续更新的请在下方留言,可以说说自己感兴趣的点,比如文本聚类和文本分类...

    2deb2e23f5411b33aa2916c03b1c2e4d.png

    展开全文
  • 一、理论篇: 在我们的场景中,文本数据量比较大,因此直接采用深度学习模型来预测文本类目的多标签,而TextCNN向来以速度快,准确率高著称。TextCNN的核心思想是抓取文本的局部特征:通过不同的卷积核尺寸(确切的...

    5ae13dcd054a80a9285cd27b3c74549c.png
    六年的大学生涯结束了,目前在搜索推荐岗位上继续进阶,近期正好在做类目预测多标签分类的项目,因此把相关的模型记录总结一下,便于后续查阅总结。

    一、理论篇:
    在我们的场景中,文本数据量比较大,因此直接采用深度学习模型来预测文本类目的多标签,而TextCNN向来以速度快,准确率高著称。TextCNN的核心思想是抓取文本的局部特征:通过不同的卷积核尺寸(确切的说是卷积核高度)来提取文本的N-gram信息,然后通过最大池化操作来突出各个卷积操作提取的最关键信息(颇有一番Attention的味道),拼接后通过全连接层对特征进行组合,最后通过交叉熵损失函数来训练模型。

    e7d6f34565a454472e5c9cfd3af7d100.png

    bf38719a9b27669c7755e0a7b64e13f3.png

    模型的第一层就是Embedding层,预训练的词嵌入可以利用其它语料库得到更多的先验知识,经过模型训练后能够抓住与当前任务最相关的文本特征。在我们的应用场景中,使用预训练的Embedding比随机初始化带来的效果不是特别显著。第二层为卷积层,CV中常见的卷积尺寸通常是正方形,而本文的卷积尺寸与之不同,本文的卷积宽度等于文本Embedding后的维度,保持不变,因为每个词或字相当于一个最小的单元,不可进一步分割。而卷积核的高度可以自定义,在向下滑动的过程中,通过定义不同的窗口来提取不同的特征向量,有点类似于N-gram过程。这样不同的kernel可以获取不同范围内词的关系,获得的是纵向的差异信息,也就是在一个句子中不同范围的词出现会带来什么信息。比如可以使用3,4,5个词数分别作为卷积核的大小),每个卷积尺寸下又有多个相同的卷积核(原因是卷积神经网络学习的是卷积核中的参数,每个filter都有自己的关注点,它们可以从同一个窗口学习相互之间互补的特征,这样多个卷积核就能学习到不同的信息,比如可以设置size为3的filter有4个卷积核)。

    第三层是最大池化层,即为从每个滑动窗口产生的特征向量中筛选出一个最大的特征,然后将这些特征拼接起来构成向量表示。也可以选用K-Max池化(选出每个特征向量中最大的K个特征),或者平均池化(将特征向量中的每一维取平均)等,达到的效果都是将不同长度的句子通过池化得到一个定长的向量表示。在短文本分类场景中,每条文本中都会有一些对分类无用的信息,而最大池化可以突出最重要的关键词以帮助模型更容易找到对应的类目。

    接下来的几层就跟具体的任务相关了,一般都会拼接特征,在通过全连接层自由组合提取出来的特征实现分类。在损失函数上,二分类和多标签分类可以采用基于Sigmoid函数的交叉熵损失函数binary_crossentropy多分类任务可以采用基于Softmax的多类别交叉熵损失函数(categorical_crossentropy)。

    二、代码部分:

    def textcnn(hyper_parameters):
        input = Input(shape=(hyper_parameters.max_len,))
        if hyper_parameters.embedding_matrix is None:
            embedding = Embedding(input_dim=hyper_parameters.vocab + 1,
                                  output_dim=hyper_parameters.emd_dim,
                                  input_length=hyper_parameters.MAX_LEN,
                                  trainable=True)(input)
        else:  # 使用预训练矩阵初始化Embedding
            embedding = Embedding(input_dim=hyper_parameters.vocab + 1,
                                  output_dim=hyper_parameters.emd_dim,
                                  weights=[hyper_parameters.embedding_matrix],
                                  input_length=hyper_parameters.MAX_LEN,
                                  trainable=False)(input)
    
        convs = []
        for kernel_size in hyper_parameters.kernel_size:
            conv = Conv1D(hyper_parameters.conv_code, kernel_size,
                          activation=hyper_parameters.relu)(embedding)
            pool = MaxPooling1D()(conv)
            convs.append(pool)
        concat = Concatenate()(convs)
        flattern = Flatten()(concat)
        dropout = Dropout(hyper_parameters.dropout)(flattern)
        output = Dense(hyper_parameters.classes, activation=hyper_parameters.sigmoid)(dropout)
        model = Model(input, output)
        model.compile(loss='binary_crossentropy',
                      optimizer='adam',
                      metrics=['accuracy'])
    
        return model

    在Embedding部分,如果有条件可以使用自己预训练的文本信息来初始化Embedding矩阵,效果可能会比随机初始化Embedding提升一点。

    三、几点思考:

    1.TextCNN能用于文本分类的主要原因是什么?

    除了预训练文本外,TextCNN通过利用不同的卷积核尺寸并行提取文本的信息(类似N-gram),并通过最大池化来突出最重要的关键词来实现分类。

    2.TextCNN的缺点:

    2.1. TextCNN的卷积和池化操作会丢失文本序列中的词汇顺序和位置信息等内容,但也可利用这一点来增强文本,例如白色旅游鞋,可以添加旅游鞋白色数据等,分词后白色和旅游鞋位置就可以互换来丰富语料 。

    2.2. 在长文本使用TextCNN效果可能没有在短文本中效果好(具体还需要实践确认),原因同上,因此可以尝试使用Top k池化替代最大池化提取更多的文本信息。

    https://arxiv.org/pdf/1408.5882.pdfarxiv.org小占同学:深入TextCNN(一)详述CNN及TextCNN原理zhuanlan.zhihu.com
    75d437d15eae7774b0f14f171921468e.png
    展开全文
  • 这篇博客主要是介绍一下我最近开源的python库——DeepClassifier,用于文本分类,目前已经集成了较多的文本分类模型,欢迎大家安装、star以及fork~ 动机首先谈谈我为什么要开发这个库。有两个原因吧~第一,我自身...
  • 前言本文将介绍基于TextCNN的文本处理相关有什么用?广泛应用于辅助决策、个性化推荐、网页分类、话题跟踪、情报过滤中比如辅助决策:在决策过程中做好分析问题、预计后果、处理不确定因素,最后进行评价与选择方案...
  • 原因:每个的位置不同,要做不同的加权 方法一般有两种: 1对不同位置的进行独热编码(比如第一个标记为1000000000) 2利用正弦余弦的周期进行表达
  • 本文重点本文中我们将学习使用文本分类模型TextCNN来完成文本的分类任务,TextCNN是应用卷积神经网络对文本数据进行分类的模型。卷积神经网络的和心思想是捕捉局部特征,对于文本来说,局部特征就是由若干单词组成的...
  • 1 大纲概述文本分类这个系列将会有十篇左右,包括基于word2vec预训练的文本分类,与及基于最新的预训练模型(ELMo,BERT等)的文本分类。总共有以下系列:jupyter notebook代码均在textClassifier仓库中,python代码在...
  • 1 文本分类文本分类是自然语言处理领域最活跃的研究方向之一,目前文本分类在工业界的应用场景非常普遍,从新闻的分类、商品评论信息的情感分类到微博信息打标签辅助推荐系统,了解文本分类技术是NLP初学者比较好的...
  • 点击上方蓝字关注我们吧导读:随着推荐...针对上述问题,本文将介绍网易信息流推荐场景下基于文本语义理解的解决方案。1业务背景网易信息流内容形态丰富多样,首页是主要的推荐页,根据用户的阅读兴趣和点击行为进...
  • 许多新入门 NLP 的小伙伴开始做 NLP 相关任务的时候,还没到...举个栗子:假如我们的语料库总共只有 10 个,那么每个经过转换之后,都会变成一个 10 维的稀疏向量。例如,将分好词的文本“我 喜欢 学习”进行 ...
  • # 筛选自定义词典中的,和各类名词,自定义词库的在没设置词性的情况下默认为x词性,即的flag词性为x if wds.flag == 'x' and wds.word != ' ' and wds.word != 'ns' or re.match(r'^n', wds.flag) != None ...
  • 其实,我们也可以将文本当作一维图像,从而可以用一维卷积神经网络来捕捉临近之间的关联。本节将介绍将卷积神经网络应用到文本分析的开创性工作之一:textCNN [1]。textCNN模型主要使用了一维卷积层和时序最大池化...
  •  output) output.close() def load_pkl(path): pkl_file = open(path, 'rb') data = pickle.load(pkl_file) pkl_file.close() return data 在词典部分,我手动加了两个特殊词条:未登录词,对应的词向量是...
  • 本文同步发布于公众号:阿黎投喂舍文本分类系列:文本分类经典论文:fasttext,textcnn解读分享 | 叮,情感分类从入门到放弃资料推荐来咯~简介上一篇文章基于深度学习的文本分类论文推荐——fasttext,textcnn介绍了...
  • 一 :今日吐槽 今天必须吐槽一下 pytorch 的文本处理库 TorchText。前几天我整理了一个 FastText 多分类模型,并用 TorchText 进行文本预处理,整个过程还算简洁清晰。结果这次做多标签分类的文本处理,就熄火了。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,906
精华内容 1,562
关键字:

文本词向量