• word2vec+回归模型实现分类任务


    使用word2vec+回归模型完全成一个分类预测任务
    数据集

    链接:https://pan.baidu.com/s/1d8IbyXcyo-uG65ZPdgkXzg
    提取码:nbpa

    1.数据预处理模型

    思路:

    • 使用pandas读取tsv数据
    • 去掉html标签
    • 移除标点
    • 分词
    • 去停用词
    • 重新组成新的句子
      (1)导包
    import re
    import numpy as np
    import pandas as pd
    import warnings
    from bs4 import BeautifulSoup
    from gensim.models.word2vec import Word2Vec
    from sklearn.model_selection import train_test_split
    from sklearn.metrics import confusion_matrix
    from sklearn.linear_model import LogisticRegression
    import nltk
    import matplotlib.pyplot as plt
    import itertools
    from tqdm import tqdm
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    (2)读取数据

    # 用pandas读入训练数据
    df = pd.read_csv('../movie_data/labeledTrainData.tsv', sep='\t', escapechar='\\')
    print('Number of reviews: {}'.format(len(df)))
    print(df)
    
    • 1
    • 2
    • 3
    • 4

    原始的数据长这样,其中都是从网上爬取的数据,夹杂这许多其他没有用的东西。
    image.png
    (3)数据预处理

    # 1.去掉HTML标签的数据,获取review这一列的100行数据
    example = BeautifulSoup(df['review'][1000], 'html.parser').get_text()
    # 2.去掉标点符号
    example_letters = re.sub(r'[^a-zA-Z]', ' ', example)
    words = example_letters.lower().split()
    # 3.获取停用词
    stopwords = {}.fromkeys([ line.rstrip() for line in open('../movie_data/stopwords.txt')])
    # 获得停用词之后,使用set集合去重复
    eng_stopwords = set(stopwords)
    # 4.去除停用词
    words_nostop = [w for w in words if w not in stopwords]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (4)清洗数据

    # 这个清洗数据的函数其实就是去标点,去停用词,大写变小写
    def clean_text(text):
        text = BeautifulSoup(text, 'html.parser').get_text()
        text = re.sub(r'[^a-zA-Z]', ' ', text)
        words = text.lower().split()
        words = [w for w in words if w not in eng_stopwords]
        return ' '.join(words)
     # 清洗数据
    words=clean_text(df['review'][1000])
    # 清洗数据添加到dataframe里
    df['clean_review'] = df.review.apply(clean_text)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    经过数据预处理,清洗后的数据就是比较正规的数据,然后我们在原始的数据中添加了一行clean_review,这一行就是清洗过的数据,我们就要拿这些数据去做训练word2vec
    image.png
    (5)分词

    # 建立分词器
    nltk.download()
    warnings.filterwarnings("ignore")
    # nltk.download('punkt')
    tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
    # 获取df中清洗过的一行新数据
    review_part = df['clean_review']
    # 显示添加clean_review之后的表格样子
    print(df.head())
    
    # 使用nltk进行分词
    def split_sentences(review):
        raw_sentences = tokenizer.tokenize(review.strip())
        sentences = [clean_text(s) for s in raw_sentences if s]
        return sentences
    sentences = sum(review_part.apply(split_sentences), [])
    print('{} reviews -> {} sentences'.format(len(review_part), len(sentences)))
    print(sentence)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    这里分词器使用的是nltk中的分词器,nltk可以能会下载失败,则就需要自己去网上下载,然后自己导入。每句话分词后,并且将所有的分完的词拼接起来,然后放到一个list中,得到数据是下面的样子。
    image.png
    (6)将分词后的句子中的词语全部单个的添加到一个list中

    sentences_list = []
    for line in sentences:
        sentences_list.append(nltk.word_tokenize(line))
    print(sentences_list)
    
    • 1
    • 2
    • 3
    • 4

    得到的分词list如下图所示,因为word2vec需要一个一个的词进行训练。

    2.word2vec模型模块

    (1)设置模型需要的参数

    # 设定词向量训练的参数
    '''
    sentences:可以是一个list
    sg: 用于设置训练算法,默认为0,对应CBOW算法;sg=1则采用skip-gram算法。
    size:是指特征向量的维度,默认为100。大的size需要更多的训练数据,但是效果会更好. 推荐值为几十到几百。
    window:表示当前词与预测词在一个句子中的最大距离是多少
    alpha: 是学习速率
    seed:用于随机数发生器。与初始化词向量有关。
    min_count: 可以对字典做截断. 词频少于min_count次数的单词会被丢弃掉, 默认值为5
    max_vocab_size: 设置词向量构建期间的RAM限制。如果所有独立单词个数超过这个,则就消除掉其中最不频繁的一个。每一千万个单词需要大约1GB的RAM。设置成None则没有限制。
    
    workers参数控制训练的并行数。
    
    hs: 如果为1则会采用hierarchica·softmax技巧。如果设置为0(defau·t),则negative sampling会被使用。
    negative: 如果>0,则会采用negativesamp·ing,用于设置多少个noise words
    iter: 迭代次数,默认为5
    '''
    num_features = 300    # Word vector dimensionality
    min_word_count = 40   # Minimum word count
    num_workers = 4       # Number of threads to run in parallel
    context = 10          # Context window size
    model_name = '{}features_{}minwords_{}context.model'.format(num_features, min_word_count, context)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    (2)训练模型

    # 9.训练模型
    model=Word2Vec(sentences_list,workers=num_workers,vector_size=num_features, min_count = min_word_count, window = context)
    model.init_sims(replace=True)
    # 保存模型
    model.save("F:\python\word2vect\model\demo3_model")
    # 测试
    # 计算这几个词的相似度,把最不相关的返回出来
    print(model.wv.doesnt_match(['man','woman','child','kitchen']))
    
    # 计算boy 相关的词
    print(model.wv.most_similar("boy"))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    第一个测试,这几个词语最不相关的就是kitchen
    第二测试结果如下
    image.png

    3.将trian,test数据转换成向量

    我们要计算的是一个整句话的词向量,不是一个一个词的向量,所以这里我们把一句话进行分词,然后再把所有分词的向量相加取得平均值.
    其实这样表达可能不是很准确,还有一个更好的tf_idf算法,以后遇到再学习.

    # 定义一个数据清洗函数清洗我们需要用来训练的数据
    def to_review_vector(review):
        global word_vec
        review = clean_text(review, remove_stopwords=True)
        # words = nltk.word_tokenize(review)
        word_vec = np.zeros((1, 300))
        for word in review:
            # word_vec = np.zeros((1,300))
            if word in list(model.wv.key_to_index):
                word_vec += np.array([model.wv[word]])
        # print (word_vec.mean(axis = 0))
        # 把300维的向量挨个挨个的放到其中,并且标记上序号
        return pd.Series(word_vec.mean(axis=0))
    # 下面这句话是pandas的一个特殊的函数,将review这个一列的数据循环放到to_review_vector中
    train_data_features = df.review.apply(to_review_vector)
    print("输出叠加之后的词向量")
    print(train_data_features.head())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    因为我们词向量设置的是300维,然后将他们叠加之后取到的平均也是300维,下面是对应每一行的review的数据的句子的向量,300个。
    image.png
    然后将需要训练的数据分成训练集和测试集,训练集80%,测试集20%

    X_train, X_test, y_train, y_test = train_test_split(train_data_features,df.sentiment,test_size = 0.2, random_state = 0)
    
    • 1

    4.线性回归模块

    # 获得逻辑回归模型
    LR_model = LogisticRegression()
    # 将训练集放到模型中训练
    LR_model = LR_model.fit(X_train, y_train)
    # 将测试数据放到其中测试
    y_pred = LR_model.predict(X_test)
    # 将真实值和预测值放到其中得到一个混淆矩阵
    cnf_matrix = confusion_matrix(y_test,y_pred
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    得到的混淆矩阵如下
    image.png

    5.可视化数据结果

    def plot_confusion_matrix(cm, classes,
                              title='Confusion matrix',
                              cmap=plt.cm.Blues):
        """
        This function prints and plots the confusion matrix.
        """
        plt.imshow(cm, interpolation='nearest', cmap=cmap)
        plt.title(title)
        plt.colorbar()
        tick_marks = np.arange(len(classes))
        plt.xticks(tick_marks, classes, rotation=0)
        plt.yticks(tick_marks, classes)
    
        thresh = cm.max() / 2.
        for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
            plt.text(j, i, cm[i, j],
                     horizontalalignment="center",
                     color="white" if cm[i, j] > thresh else "black")
    
        plt.tight_layout()
        plt.ylabel('True label')
        plt.xlabel('Predicted label')
    # Plot non-normalized confusion matrix
    class_names = [0,1]
    plt.figure()
    plot_confusion_matrix(cnf_matrix, classes=class_names,title='Confusion matrix')
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    这函数就是可视化混淆矩阵,通过上面可视化的混淆矩阵,可以得到以下数据。
    image.png
    在混淆矩阵中,深蓝色的是预测正确的值,灰白色的是预测错误的。

    评估模型

    一般评估模型用精确度,召回率,F1值来评估

    TP:(实际为正例,预测也为正例) 实际为男生,预测为男生;
    FP:(实际为负例,预测为正例) 实际为女生,预测为男生;
    FN:(实际为正例,预测为负例) 实际为男生,预测为女生;
    TN:(实际为负例,预测也为负例) 实际为女生,预测为女生;

    计算公式:

    准确率(Accuracy) = (TP + TN) / 总样本 。
    定义是: 对于给定的测试数据集,分类器正确分类的样本数与总样本数之比。

    精确率(Precision) = TP / (TP + FP) 。
    它表示:预测为正的样本中有多少是真正的正样本,它是针对我们预测结果而言的.Precision又称为查准率。

    召回率(Recall) = TP / (TP + FN)
    它表示:样本中的正例有多少被预测正确了, 它是针对我们原来的样本而言的。Recall又称为查全率。

    F1=(2 x precision x recall)/(precision+recoall)
    F1值是召回率和精确度的一个平均计算方式

    代码如下

    print("accuracy(test): ", (cnf_matrix[1,1]+cnf_matrix[0,0])/(cnf_matrix[0,0]+cnf_matrix[1,1]+cnf_matrix[1,0]+cnf_matrix[0,1]))
    print("precision:",(cnf_matrix[0,0])/(cnf_matrix[0,0]+cnf_matrix[1,0]))
    print("Recall metric in the testing dataset: ", cnf_matrix[1,1]/(cnf_matrix[1,0]+cnf_matrix[1,1]))
    
    • 1
    • 2
    • 3

    就是那结果如下:

    accuracy(test):  0.861
    precision: 0.8773930753564155
    Recall :  0.8772430668841762
    
    • 1
    • 2
    • 3
  • 相关阅读:
    kubernetes架构及核心组件简单介绍
    13、Java——“21点”扑克游戏系统(变量+循环)
    图文讲解IDEA如何导入JDBC驱动包
    阿里云r7服务器内存型CPU采用
    MySQL和SQLserver中group by的区别
    【软考】9.3 二叉树存储/遍历/线索/最优/查找/平衡
    java源码系列:HashMap底层存储原理详解——3、技术本质-原理过程-算法之哈希算法、哈希code、ascii码计算、取模运算等
    部署LVS-DR群集
    信创云:打造自主可控云基础设施 | 厂商征集
    RCC目前最近技术与今后发展
  • 原文地址:https://blog.csdn.net/qq_35653657/article/details/126003379