一、文本分类任务描述:input—model—output
二、应用场景:
# One Hot编码(独热编码)实战
import numpy as np
# 0:语料准备
corpus = ['这 是 第一个 文档',
'这是 第二个 文档',
'这是 最后 一个 文档',
'现在 没有 文档 了']
# 1:手动实现
# 词袋
words = []
for corpu in corpus:
words.extend(corpu.split())
# 词的列表(去重)
word_list = list(set(words))
# 生成字典
word_dct = {word: index for index, word in enumerate(word_list)}
# 词典大小
vocab_size = len(word_dct)
# print(word_dct)
# {'了': 0, '这是': 1, '这': 2, '最后': 3, '第二个': 4, '第一个': 5, '一个': 6, '是': 7, '没有': 8, '文档': 9, '现在': 10}
def get_one_hot(index):
# 获得一个one hot编码
one_hot = [0 for _ in range(vocab_size)]
one_hot[index] = 1
return np.array(one_hot)
# print(get_one_hot(1)) # [0 1 0 0 0 0 0 0 0 0 0]
# 第一句话
indexs = [word_dct[word] for word in corpus[0].split()]
# 转换成one hot
one_hot_np = np.array([get_one_hot(index) for index in indexs])
# print(one_hot_np)
'''
[[0 0 1 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 1 0 0 0]
[0 0 0 0 0 1 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 1 0]]
'''
# 2 Sklearn实现
from sklearn.preprocessing import LabelBinarizer
# 初始化编码器
lb = LabelBinarizer()
# 将所有分好的的词都放进去
lb.fit(words)
lb.classes_
# 初始化句子
sentence = corpus[0].split()
print(sentence)
# ['这', '是', '第一个', '文档']
LB = lb.transform(sentence)
print(LB)
'''
[[0 0 0 0 0 0 0 0 0 1 0]
[0 0 0 1 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 1 0 0 0]
[0 0 1 0 0 0 0 0 0 0 0]]
'''
# 解码
LB_inverse = lb.inverse_transform(LB)
print(LB_inverse)
# ['这' '是' '第一个' '文档']
1、词频(TF)
2 、逆文件频率(IDF)
3 、TF-IDF
4、TF-IDF的缺点
# 词频-逆文件频率
# 0:语料准备
corpus = ['这 是 第一个 文档',
'这是 第二个 文档',
'这是 最后 一个 文档',
'现在 没有 文档 了 文档']
# 1、手动实现
# 1.1 词袋统计
words_list = []
for corpu in corpus:
words_list.append(corpu.split())
print(words_list)
# [['这', '是', '第一个', '文档'], ['这是', '第二个', '文档'], ['这是', '最后', '一个', '文档'], ['现在', '没有', '文档', '了', '文档']]
# 1.2统计词频
from collections import Counter
count_list = []
for words in words_list:
count = Counter(words)
count_list.append(count)
print(count_list)
# [Counter({'这': 1, '是': 1, '第一个': 1, '文档': 1}),
# Counter({'这是': 1, '第二个': 1, '文档': 1}),
# Counter({'这是': 1, '最后': 1, '一个': 1, '文档': 1}),
# Counter({'文档': 2, '现在': 1, '没有': 1, '了': 1})]
# 1.3 定义函数
import math
def tf(word, count):
return count[word]/sum(count.values())
def idf(word, count_list):
n_contain = sum([1 for count in count_list if word in count])
return math.log(len(count_list)/(1+n_contain))
def tf_idf(word, count, count_list):
return tf(word, count)*idf(word, count_list)
# 1.4 输出结果
for index, count in enumerate(count_list):
print('第{}个文档的TF IDF的信息;'.format(index+1))
# 分值
scores = {word: tf_idf(word, count, count_list) for word in count}
scores_word = sorted(scores.items(), key=lambda x: x[1], reverse=True)
for word,score in scores_word:
print('word:{}, TF IDF : {} '.format(word, round(score, 5)))
'''
第1个文档的TF IDF的信息;
word:这, TF IDF : 0.17329
word:是, TF IDF : 0.17329
word:第一个, TF IDF : 0.17329
word:文档, TF IDF : -0.05579
第2个文档的TF IDF的信息;
word:第二个, TF IDF : 0.23105
word:这是, TF IDF : 0.09589
word:文档, TF IDF : -0.07438
第3个文档的TF IDF的信息;
word:最后, TF IDF : 0.17329
word:一个, TF IDF : 0.17329
word:这是, TF IDF : 0.07192
word:文档, TF IDF : -0.05579
第4个文档的TF IDF的信息;
word:现在, TF IDF : 0.13863
word:没有, TF IDF : 0.13863
word:了, TF IDF : 0.13863
word:文档, TF IDF : -0.08926
'''
# 2、Gensim
# 2.1 词袋统计
# 2.2 获取词频
from gensim import corpora
dic = corpora.Dictionary(words_list) # 这是一个对象
# print(dic)
# doc2bow()传入的是一个词的列表
new_corpus = [dic.doc2bow(words) for words in words_list]
# 第一个元素是词在词典中的id, 第二个是词在文档中出现的次数
print(new_corpus)
# [[(0, 1), (1, 1), (2, 1), (3, 1)], -----['这', '是', '第一个', '文档']
# [(0, 1), (4, 1), (5, 1)],
# [(0, 1), (5, 1), (6, 1), (7, 1)],
# [(0, 2), (8, 1), (9, 1), (10, 1)]] ----['现在', '没有', '文档', '了', '文档']
# 2.3 每一个词对应的id
print(dic.token2id)
# {'文档': 0, '是': 1, '第一个': 2, '这': 3, '第二个': 4, '这是': 5, '一个': 6, '最后': 7, '了': 8, '没有': 9, '现在': 10}
from gensim import models
tfidf = models.TfidfModel(new_corpus)
# 保存模型
tfidf.save('tfidf.model')
# 加载模型
tfidf = models.TfidfModel.load('tfidf.model')
tf_idf_vec = []
for corpu in corpus:
# 先拿到第一个文档
doc_bow = dic.doc2bow(corpu.lower().split())
vec = tfidf[doc_bow]
tf_idf_vec.append(vec)
print(tf_idf_vec)
# 一个列表对应一个文章
# [[(1, 0.5773502691896258),(2, 0.5773502691896258), (3, 0.5773502691896258)],
# [(4, 0.8944271909999159), (5, 0.4472135954999579)],
# [(5, 0.3333333333333333), (6, 0.6666666666666666), (7, 0.6666666666666666)],
# [(8, 0.5773502691896258),(9, 0.5773502691896258), (10, 0.5773502691896258)]]
# 3、Sklearn
from sklearn.feature_extraction.text import TfidfVectorizer
# 初始化对象
tfidf_vec = TfidfVectorizer()
# 加载所有语料
tf_idf_matrix = tfidf_vec.fit_transform(corpus)
# 得到语料库中所有不重复的词
print(tfidf_vec.get_feature_names())
# ['一个', '文档', '最后', '没有', '现在', '第一个', '第二个', '这是']
# 得到所有单词对应的id
print(tfidf_vec.vocabulary_)
# {'第一个': 5, '文档': 1, '这是': 7, '第二个': 6, '最后': 2, '一个': 0, '现在': 4, '没有': 3}
# 获得tf idf 矩阵输出
print(tf_idf_matrix.toarray())
'''
[[0. 0.46263733 0. 0. 0. 0.88654763 0. 0. ]
[0. 0.37919167 0. 0. 0. 0. 0.72664149 0.5728925 ]
[0.58783765 0.30675807 0.58783765 0. 0. 0. 0. 0.46345796]
[0. 0.59380024 0. 0.56894695 0.56894695 0. 0. 0. ]]
'''
单词嵌入向量(Word Embedding)
数据集:
今日头条中文新闻(短文本)分类
地址:https://storage.googleapis.com/cluebenchmark/tasks/tnews_public.zip
import pandas as pd
import json
import jieba
'''
0:gensim词向量实践
1、读取预处理的数据集
2、训练
3、结果
'''
# 1、下载数据
# 1.1 数据预处理
def get_sentence(data_file):
# 读取文件
f = open(data_file, 'r', encoding='utf-8')
reader = f.readlines()
sentence = []
for line in reader:
line = json.loads(line.strip())
sentence.append(line['sentence'])
return sentence
train_sentence = get_sentence('train.json')
test_sentence = get_sentence('test.json')
dev_sentence = get_sentence('dev.json')
# 2、载入数据
train_data = train_sentence + test_sentence + dev_sentence
# print(len(train_data)) # 73360
# 分词
train_data = [list(jieba.cut(sentence)) for sentence in train_data]
# 3、构建词向量模型
from gensim.models.word2vec import LineSentence
from gensim.models import word2vec
import gensim
import logging
logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s', level=logging.INFO)
# 构建模型
from gensim.models import FastText
# print(help(FastText))
# model = FastText(test_sentence, vector_size=4, window=3, min_count=1)
# 4、训练模型 skip-gram(sg = 1) & CBOW(sg = 0)
model = word2vec.Word2Vec(train_data, sg=0, workers=8, min_count=5, vector_size=200)
# 5、保存模型
model_save_path = 'word2vec.model'
model.save(model_save_path)
# 6、载入模型
model = word2vec.Word2Vec.load(model_save_path)
# 输出向量维度(1x200) 上面定义的vector_size=200
print(model.wv['智能'].shape)
'''
输出:
(200,)
'''
# 查找一个上下文最近的词
print(model.wv.most_similar(['智能'], topn=10))
'''
输出:
[('金融', 0.970018208026886),
('生态', 0.9675754308700562),
('赋能', 0.9635003209114075),
('服务', 0.9610007405281067),
('电商', 0.9590190052986145),
('创新', 0.9575081467628479),
('布局', 0.956716775894165),
('建设', 0.9556843042373657),
('助力', 0.9543666839599609),
('云', 0.9498512148857117)]
'''
一对一策略:
一对其余策略:
在建模上区别:
# 激活函数练习
# sigmoid
import numpy as np
import matplotlib.pyplot as plt
def sigmoid(x):
return 1.0/(1+np.exp(-x))
# print(sigmoid(1))
'''
0.7310585786300049
'''
sigmoid_input = np.arange(-10, 10)
sigmoid_output = sigmoid(sigmoid_input)
# print(sigmoid_output)
'''
[4.53978687e-05 1.23394576e-04 3.35350130e-04 9.11051194e-04
2.47262316e-03 6.69285092e-03 1.79862100e-02 4.74258732e-02
1.19202922e-01 2.68941421e-01 5.00000000e-01 7.31058579e-01
8.80797078e-01 9.52574127e-01 9.82013790e-01 9.93307149e-01
9.97527377e-01 9.99088949e-01 9.99664650e-01 9.99876605e-01]
'''
# plt.plot(sigmoid_input, sigmoid_output)
# plt.xlabel('sigmoid_input')
# plt.ylabel('sigmoid_output')
# plt.show()
# softmax
import math
softmax_input = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]
z_exp = [math.exp(i) for i in softmax_input]
print(z_exp)
'''
[2.718281828459045, 7.38905609893065, 20.085536923187668, 54.598150033144236,
2.718281828459045, 7.38905609893065, 20.085536923187668]
'''
sum_z_exp = sum(z_exp)
softmax_output = [round(ex/sum_z_exp, 2) for ex in z_exp]
print(softmax_output)
'''
[0.02, 0.06, 0.17, 0.47, 0.02, 0.06, 0.17]
'''
# 画图
plt.plot(softmax_input, softmax_output)
plt.xlabel('softmax_input')
plt.ylabel('softmax_output')
plt.show()
1、embedded层:将句子或文章平铺为词向量
2、进入多层卷积层(卷积核大小不同):算出每个卷积核卷积后的特征值
3、进入池化层:提取出上一步最大的特征值(max pooling)
4、连接:将最大的特征值拼接在一起
5、套一个dropout:防止过拟合
6、进入全连接层:分类(两类或者多类)
1、评价指标
2、混淆矩阵:(指标:准确率、召回率、精确率)
3、预测的效果?
假设样本不平衡:(<0.5 分为0,>0.5分为1)
如果不使用模型,直接计算:
线越靠近左上角效果越好 (SKlearn调用roc_auc_score)
中文NLP语料库:
https://www.cluebenchmarks.com/
NLP学习框架:BERT
国内可以一件加载模型:
免费的GPU: