Datawhale-新闻文本分类-task4-基于深度学习的文本分类2-word2vec-textcnn-textrnn

# 在上一次中10fold代码不知道怎么写![](https://img2020.cnblogs.com/blog/1358638/202007/1358638-20200731212605021-1488696390.png) , 之后看了论坛大哥代码,有点理解了。

# 10_kfold fucntion
import logging
import random
fold_num = 10
data_file = './train_set.csv'
import pandas as pd
import numpy as np

logging.basicConfig(level=logging.INFO, format='%(asctime)-15s %(levelname)s: %(message)s')

def all_data2fold(fold_num, num=10000):
    # 
    fold_data = []
    f = pd.read_csv(data_file, sep='	', encoding='utf-8')
    texts = f['text'].tolist()[:num]  # 得到所有text
    labels = f['label'].tolist()[:num] # 得到所有text对应的Label
    
    
    total = len(labels)  # 得到样本总数量
    
    index = list(range(total))  # 制造所有样本对应的index
#     print(index[:100])
    np.random.shuffle(index) # 打乱所有index顺序
#     print(index[:100])    
    
    all_texts = []  # 存放所有texts
    all_labels = [] # 存放所有labels
    for i in index: # 将打乱顺序的样本和label全部放入刚建的all_text List 和 all_labels List
        all_texts.append(texts[i])  # all_texts 和 texts 都存放了所有的样本, 但前者是无序,后者是有序
        all_labels.append(labels[i])  # all_labels 和 labels 都存放了所有的label, 但前者是无序,后者是有序
    
    # 这小段代码将得到每个标签对应的样本所在的index。  存放在label2id中, 
    label2id = {}
    for i in range(total):
        label = str(all_labels[i])
        if label not in label2id:
            label2id[label] = [i]
        else:
            label2id[label].append(i)
#     print(label2id.get('10'))
    
    
    all_index = [[] for _ in range(fold_num)] # 生成一个二维的10个空list。 [[],[],[],[],[],[],[]……]
#     print(all_index)
    
    for label, data in label2id.items(): # label:样本标签, data: label对应的样本list
        # print(label, len(data))
        batch_size = int(len(data) / fold_num)  # 求得每类label对应的所有样本 / 10 得平均数
        other = len(data) - batch_size * fold_num # 求得多出得样本数量 (求未整除10时,剩余样本数量) 就是按除以10得平均数分完10份后,还剩余得样本数
        
        # 这小段代码时切分十折样本得逻辑: 将多出的样本随机分给10份中某些部分
        for i in range(fold_num):
            cur_batch_size = batch_size + 1 if i < other else batch_size  # 将多出的样本随机分给10份中某些部分
            # i * batch_size:表示在10轮顺序中所处取号排名;b代表在当前每个fold对应应取数目中的排名。
            #因此 i * batch_size + b表示:在label所有对应样本中应取排名
            batch_data = [data[i * batch_size + b] for b in range(cur_batch_size)]  # 拿着上一步分得的应取样本数目到label对应存放样本的data中取
            # 将每个fold取到的样本对应index存到all_index中
            all_index[i].extend(batch_data)  # 注意此处是extend,而不是append,因此一个[]就包含该fold所有类别label对应的样本index
            # 当这小段代码运行结束,所有样本的十折分区就已经分好了。
            # all_index是这样得: [[所有被分到label对应样本的index], [], ……共10个]
    
    # 之前得代码是划分10fold中没fold应取样本得index
    # 这段代码是:取出每个fold对应得样本,label
    batch_size = int(total / fold_num)  # 表示10fold中,每个fold应取得总样本数目为多少。(所有label)
    other_texts = []
    other_labels = []
    other_num = 0
    start = 0
    
    # 
    print(total)
    for fold in range(fold_num):
        count = 0
        num = len(all_index[fold]) # 该fold取得的样本总数量
        texts = [all_texts[i] for i in all_index[fold]] # 取出该fold对应得样本
        fold_labels = [all_labels[i] for i in all_index[fold]]  # 取出该fold对应得label
#         print(batch_size == len(fold_labels), end='')
        
        
        # 这段代码逻辑则是让每个fold对应的样本和label数量与  总样本数量/fold_num  尽可能相等(至少保证前面几个fold)
        # 但是我不明白这样做有什么意义:因为这样可能导致有样本没有分到10fold中。
        # 举例总样本26,两类。第一类12,第二类14个
        # 按分法,10fold。[[2,2,1,1,1,1,1,1,1,1], [2,2,2,2,1,1,1,1,1,1]] 
        # 那么---> 每个fold对应样本数量[[4],[4],[3],[3],[2],[2],[2],[2],[2],[2]]
        # 总样本数量 / 10fold = 26 /10 = 2.6, 再int 得 avg = 2 ; 将avg与之前folf对应样本数量比较,再划分得到新的每folf对应样本数量
        # ---> [[2],[2],[2],[2],[2],[2],[2],[2],[2],[2]]   , 那么还有6个样本呢? 不在10fold中了? 
        ######  从测试得结果看,我的猜想是错误得, 这段代码没有问题, 并且降低了最大与最小fold样本差
        if num > batch_size:
            fold_texts = texts[:batch_size]
            other_texts.extend(texts[batch_size:])
            fold_labels= labels[:batch_size]
            other_labels.extend(labels[batch_size:])
            other_num += num - batch_size
        elif num < batch_size:
            end = start + batch_size - num
            fold_texts = texts + other_texts[start: end]
            fold_labels = labels + other_labels[start: end]
            start = end
        else:
            fold_texts = texts
            fold_labels = labels
        count += len(fold_labels)
#         print(count)
#         print(batch_size == len(fold_labels))
#         assert  batch_size == len(fold_labels)

        # shuffle
        # 再次打乱顺序是此时, 每个label样本是没有被分开得,label对应样本都聚在一起了
        index = list(range(batch_size)) 
        np.random.shuffle(index)
        
        shuffle_fold_texts = []
        shuffle_fold_labels =[]
        
        for i in index:
            shuffle_fold_texts.append(fold_texts[i])
            shuffle_fold_labels.append(fold_labels[i])
        data = {'label': shuffle_fold_labels, 'text': shuffle_fold_texts}
        fold_data.append(data)
        
    logging.info('Fold lens %s', str([len(data['label']) for data in fold_data]))
    
    return fold_data

fold_data = all_data2fold(10)

word2vec 得到词向量。 我觉得word2vec牛皮得地方在于它得思想,联系上下文,计算得到相似度。那么按这个原理,就可以在其它地方得到应用了。我想到了推荐(商品、视频、好友、文章等)
为了验证自己得猜想,搜了“word2vec可以做推荐吗?” 果然有很多文章在介绍word2vec在推荐上得应用。
但是目前自己还是太菜了。所以并不知道,拿到词向量后怎么样在其它算法中使用?

下面继续摘抄论坛大哥得代码完成打卡。
但是textcnn、textrnn。 代码PyTorch写的,在注释得情况下,还是看不懂。 所以暂时先提交到word2vec。其它的后面搞懂了再补上

#####
# # build train data for word2vec
fold_id = 9

# 按k fold 取出data作为train_texts
train_texts = []
for i in range(0, fold_id):
    data = fold_data[i]
    train_texts.extend(data['text'])
    
logging.info('Total %d docs.'% len(train_texts))

logging.info('Start trainig……')
from gensim.models.word2vec import Word2Vec

num_features = 100
num_workers = 8

# train_texts 是个二维list,使用map
train_texts = list(map(lambda x: list(x.split()), train_texts))

model = Word2Vec(train_texts, workers=num_workers, size=num_features)
model.init_sims(replace=True)  # 锁定模型,可以提高后续模型和任务速度。但是模型也不能再训练了。

# save model
model.save('./word2vec.bin')

# load model
model = Word2Vec.load('./word2vec.bin')

# convert format
model.wv.save_word2vec_format('./word2vec.txt', binary=False)
原文地址:https://www.cnblogs.com/Alexisbusyblog/p/13412304.html