【DKN】(三)data_preprogress.py

本文介绍了如何解析行为数据,处理news文件,使用Glove词嵌入和RoBERTa模型生成用户行为和新闻特征,以及转换和整合各类标签信息。核心内容包括用户行为编码、新闻文本处理、预训练模型应用及数据转换。
摘要由CSDN通过智能技术生成

内容

try:    # 以绝对导入的方式导入cofig对象,并获取其{model_name}Config! 
    config = getattr(importlib.import_module('config'), f"{model_name}Config")
except AttributeError:
    print(f"{model_name} not included!")
    exit()

这里就是config下的属性类

  • 下面是解析behavior.tsv文件, behavior.tsv文件如下;
    在这里插入图片描述

这就是user-1的clicked News
在这里插入图片描述

共有五列: 分别是’impression_id’, ‘user’, ‘time’, ‘clicked_news’, ‘impressions’! 但是文件中没有给出列明的,需要自己来定义!

  • 下面是解析后的behavior_parsed.tsv文件:
    在这里插入图片描述

def parse_behaviors()

def parse_behaviors(source, target, user2int_path):
    """
    Parse behaviors file in training set.
    Args:
        source: source behaviors file
        target: target behaviors file
        user2int_path: path for saving user2int file
    """
    print(f"Parse {source}")

    behaviors = pd.read_table(
        source,
        header=None,
        names=['impression_id', 'user', 'time', 'clicked_news', 'impressions'])
    behaviors.clicked_news.fillna(' ', inplace=True)  #使用空格来填充缺失值,并修改原文件
    behaviors.impressions = behaviors.impressions.str.split()  #以空字符为分隔符来切分字符串,并返回list列表,没有指定num,所以是全部分割

    user2int = {}  #定义空字典,用于存储用户转为索引
    for row in behaviors.itertuples(index=False):   #将DataFrame转换为tuple并访问每行
        if row.user not in user2int:                #如果该用户没有在字典中
            user2int[row.user] = len(user2int) + 1  #usr2int["U87243"] = 0 + 1,也就是给定索引,记得是从1开始的,不是从0! 

	#最普通的创建DataFrame方法,其中data = user2int.items(),是元组数组; index自动; columns = user 和 int
	#将该DataFrame转换为csv文件, 分隔符是"\t",一个tab!  不保留原来的索引
    pd.DataFrame(user2int.items(), columns=['user', 
                                            'int']).to_csv(user2int_path,
                                                           sep='\t',
                                                           index=False)
                                        
    print(  #处理完数据了,看看有多少有效的user_int
        f'Please modify `num_users` in `src/config.py` into 1 + {len(user2int)}'
    )
 	#获取了df矩阵中底index行,第'user'列! 也就是将用户名改成index
    for row in behaviors.itertuples():  
        behaviors.at[row.Index, 'user'] = user2int[row.user]

	#进度条展示! 名字是Balancing data,遍历的是整个文件
    for row in tqdm(behaviors.itertuples(), desc="Balancing data"):
    	#上面可以查看behaviors中的impression属性是什么! 
    	#我们遍历每个用户的impression,然后选择尾号为1和0的分别将其封印为list后再变成可迭代的!
    	#其中错误的样本需要进行shuffle,洗牌,再装成可迭代对象
        positive = iter([x for x in row.impressions if x.endswith('1')])
        negative = [x for x in row.impressions if x.endswith('0')]
        random.shuffle(negative)
        negative = iter(negative)
        pairs = []
        try:
            while True:  #这就是一个用户要他所有正样本加上两个负样本! 
                pair = [next(positive)]
                #negative_sampling_ratio = 2  # K
                for _ in range(config.negative_sampling_ratio):
                    pair.append(next(negative))
                pairs.append(pair)
        except StopIteration:
            pass
        behaviors.at[row.Index, 'impressions'] = pairs  #取完后,再换回原behaviors
	
	# 数据消除空白值,并且重新索引!
    behaviors = behaviors.explode('impressions').dropna(
        subset=["impressions"]).reset_index(drop=True)
    #创建新的列,列名为:'candidate_news', 'clicked'
    #在pandas,map()会对behaviors.impressions的元素进行操作
    behaviors[['candidate_news', 'clicked']] = pd.DataFrame(
        behaviors.impressions.map(
            lambda x: (' '.join([e.split('-')[0] for e in x]), ' '.join(
                [e.split('-')[1] for e in x]))).tolist())
    #将某些列转为csv文件
    behaviors.to_csv(
        target,
        sep='\t',
        index=False,
        columns=['user', 'clicked_news', 'candidate_news', 'clicked'])

def parse_news()

new.tsv中的内容:
前4个列: ‘id’, ‘category’, ‘subcategory’, ‘title’,
在这里插入图片描述
后3列:‘abstract’, ‘title_entities’, ‘abstract_entities’
在这里插入图片描述

其中倒数后两列中的标签信息:
在这里插入图片描述
在这里插入图片描述
Label/ Type/ WikidataId/ Confidence/ OccurrenceOffsets/ SurfaceForms/

def parse_news(source, target, roberta_output_dir, category2int_path,
               word2int_path, entity2int_path, mode):
   #这个直接就是英文了, 就是说模式不同,这几个参数的意义也就不同了!
   #如果是训练模式,那么这个路径就是要保存的解析的 如果是测试模式,那么就是需要加载了 
    """
    Parse news for training set and test set
    Args:
        source: source news file
        target: target news file
        if mode == 'train':
            category2int_path, word2int_path, entity2int_path: Path to save
        elif mode == 'test':
            category2int_path, word2int_path, entity2int_path: Path to load from
    """
    print(f"Parse {source}")  
    news = pd.read_table(source,  #读入源文件
                         header=None,
                         usecols=[0, 1, 2, 3, 4, 6, 7],
                         quoting=csv.QUOTE_NONE,
                         names=[
                             'id', 'category', 'subcategory', 'title',
                             'abstract', 'title_entities', 'abstract_entities'
                         ])  # TODO try to avoid csv.QUOTE_NONE
    news.title_entities.fillna('[]', inplace=True)  #处理空值,并用[]来覆盖
    news.abstract_entities.fillna('[]', inplace=True)
    news.fillna(' ', inplace=True)

    tokenizer = RobertaTokenizer.from_pretrained("roberta-base")  #需要读入预训练模型
    title_roberta = tokenizer(news.title.tolist(),  #将一个句子进行简单的切分! 
                              padding='max_length',  
                              truncation=True,      #超出padding部分截断
                              max_length=config.num_words_title) 
    abstract_roberta = tokenizer(news.abstract.tolist(),   #同上! 也是这样的定义方式
                                 padding='max_length',
                                 truncation=True,
                                 max_length=config.num_words_abstract)

    roberta_df = pd.DataFrame(data=[   #  words的ids
        title_roberta['input_ids'], title_roberta['attention_mask'],
        abstract_roberta['input_ids'], abstract_roberta['attention_mask']
    ]).T
    roberta_df.columns = [    #重定义列名
        'title_roberta', 'title_mask_roberta', 'abstract_roberta',
        'abstract_mask_roberta'
    ]
    
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    for x in [title_roberta, abstract_roberta]:    #经过Tokenizer后是一个字典,存放着分割后的words的id以及mask的id
        for key in x.keys():              #我们访问该字典的两个属性
            x[key] = torch.tensor(x[key]).to(device)   #将该属性下的id放入到GPU上
    #根据给出的路径来创建目录
    Path(roberta_output_dir).mkdir(parents=True, exist_ok=True) 
    
    # roberta = RobertaModel.from_pretrained('roberta-base',
    #                                        return_dict=True).to(device)
    #嵌入RobertModel! 前面的Tokenizer是预处理! 进行分词
    if torch.cuda.device_count() > 1:
        roberta = RobertaModel.from_pretrained('roberta-base',return_dict=True)
        roberta = torch.nn.DataParallel(roberta)
        print(next(roberta.parameters()).device)  # 输出:cpu或者是cuda
        roberta.to(device)
        print(next(roberta.parameters()).device)  # 输出:cpu或者是cuda

    with torch.no_grad():     #不需要梯度更新
        title_last_hidden_state = []
        title_pooler_output = []
        abstract_last_hidden_state = []
        abstract_pooler_output = []
        for count in tqdm(range(math.ceil(len(news) / config.batch_size)),  #将news分批次
                          desc="Calculating news embeddings with RoBERTa"):
            title_roberta_minibatch = { 
                k: v[count * config.batch_size:(1 + count) * config.batch_size]
                for k, v in title_roberta.items()
            }
         # 这里的意思就是: 我们遍历访问title_roberta一部分,也就是第count个batch_size,它的索引是(count * config.batch_size:(1 + count) * config.batch_size)并放到minibatch字典!
         # 后面有关于dict.items()的介绍!
         
            title_outputs = roberta(**title_roberta_minibatch)# **代表的是提取字典中的键对儿值,也就是一对!  并处理 
            title_last_hidden_state.append(   #将输出结果放到预先定义的列表中,后面的同理
                title_outputs['last_hidden_state'].cpu().numpy())
            title_pooler_output.append(
                title_outputs['pooler_output'].cpu().numpy())

            abstract_roberta_minibatch = {
                k: v[count * config.batch_size:(1 + count) * config.batch_size]
                for k, v in abstract_roberta.items()
            }
            abstract_outputs = roberta(**abstract_roberta_minibatch)
            abstract_last_hidden_state.append(
                abstract_outputs['last_hidden_state'].cpu().numpy())
            abstract_pooler_output.append(
                abstract_outputs['pooler_output'].cpu().numpy())

		#将处理后的结果保存到文件中
        np.save(path.join(roberta_output_dir, 'title_last_hidden_state.npy'), 
                np.concatenate(title_last_hidden_state, axis=0))
        np.save(path.join(roberta_output_dir, 'title_pooler_output.npy'),
                np.concatenate(title_pooler_output, axis=0))
        np.save(
            path.join(roberta_output_dir, 'abstract_last_hidden_state.npy'),
            np.concatenate(abstract_last_hidden_state, axis=0))
        np.save(path.join(roberta_output_dir, 'abstract_pooler_output.npy'),
                np.concatenate(abstract_pooler_output, axis=0))

def parse_row(row):

entity_confidence_threshold = 0.5
news.tsv中后两列: ‘title_entities’, ‘abstract_entities’
**这个单元格: [ {}, {} ]**是一个list!
倒数第二列

倒数第一列
news.tsv第二列: category
在这里插入图片描述

 def parse_row(row):   #category转为int! 
 		#new_row = [row.id, category2int[?], 
 		#category2int[!], num_words_title个0组成的list, 同上, 同上, 同上]
        new_row = [
            row.id,
            category2int[row.category] if row.category in category2int else 0,  
            category2int[row.subcategory] if row.subcategory in category2int else 0,
            [0] * config.num_words_title, [0] * config.num_words_abstract,
            [0] * config.num_words_title, [0] * config.num_words_abstract
        ]

        # Calculate local entity map (map lower single word to entity)
        local_entity_map = {}
        for e in json.loads(row.title_entities):  #遍历访问list元素, 每一个元素就是一个字典
        #查看该news的属性,是不是置信度够高!  维基数据ID是不是在实体中 
            if e['Confidence'] > config.entity_confidence_threshold and e[
                    'WikidataId'] in entity2int: 
        #' '.join()用空格来分割字符
        #lower().split():将分割后的字符改为小写后再默认以空格符来分割成多个字符串
                for x in ' '.join(e['SurfaceForms']).lower().split():
                    local_entity_map[x] = entity2int[e['WikidataId']]  #将实体每个字符都设置为实体的标签
        for e in json.loads(row.abstract_entities):  #同上
            if e['Confidence'] > config.entity_confidence_threshold and e[
                    'WikidataId'] in entity2int:
                for x in ' '.join(e['SurfaceForms']).lower().split():
                    local_entity_map[x] = entity2int[e['WikidataId']]

        try:
            for i, w in enumerate(word_tokenize(row.title.lower())):  #将标题切tokens
                if w in word2int: #如果该单词在word2int中,那么就记住该单词的int值放到num[3][i]列表中
                    new_row[3][i] = word2int[w]
                    if w in local_entity_map:   #如果该单词在局部实体图中
                        new_row[5][i] = local_entity_map[w]
        except IndexError:
            pass

        try:
            for i, w in enumerate(word_tokenize(row.abstract.lower())):  #将摘要切tokens
                if w in word2int:
                    new_row[4][i] = word2int[w]
                    if w in local_entity_map:
                        new_row[6][i] = local_entity_map[w]
        except IndexError:
            pass

        return pd.Series(new_row,  #放入到dataFrame,并返回
                         index=[
                             'id', 'category', 'subcategory', 'title',
                             'abstract', 'title_entities', 'abstract_entities'
                         ])

后面同样是def parse_news()函数中

 if mode == 'train':
        category2int = {}  #类别转化为int
        word2int = {}   #单词转为int
        word2freq = {}  #单词转为频度
        entity2int = {} #实体转为int
        entity2freq = {}  #实体转为频度

        for row in news.itertuples(index=False):    # 遍历新闻的每个元组
            if row.category not in category2int:    # 如果该行的类别不在category2int
                category2int[row.category] = len(category2int) + 1
            if row.subcategory not in category2int: # 如果子类别不在category2int中
                category2int[row.subcategory] = len(category2int) + 1

            for w in word_tokenize(row.title.lower()): #row.title.lower()
                if w not in word2freq:   #如果w不在word2freq,就是1; 否则后面加1
                    word2freq[w] = 1
                else:
                    word2freq[w] += 1
            for w in word_tokenize(row.abstract.lower()):
                if w not in word2freq:  #后面都是这样的
                    word2freq[w] = 1
                else:
                    word2freq[w] += 1

            for e in json.loads(row.title_entities):  #times就是等于len([12])*0.99
                times = len(e['OccurrenceOffsets']) * e['Confidence']
                if times > 0:
                    if e['WikidataId'] not in entity2freq: # 实体转为频度
                        entity2freq[e['WikidataId']] = times
                    else:
                        entity2freq[e['WikidataId']] += times

            for e in json.loads(row.abstract_entities): #摘要
                times = len(e['OccurrenceOffsets']) * e['Confidence']
                if times > 0:
                    if e['WikidataId'] not in entity2freq:
                        entity2freq[e['WikidataId']] = times
                    else:
                        entity2freq[e['WikidataId']] += times

        for k, v in word2freq.items(): #遍历word2freq的key值和values值
            if v >= config.word_freq_threshold:
                word2int[k] = len(word2int) + 1

        for k, v in entity2freq.items():
            if v >= config.entity_freq_threshold:
                entity2int[k] = len(entity2int) + 1

        parsed_news = news.swifter.apply(parse_row, axis=1)  #将parse_row()函数用在news的行
        parsed_news = pd.concat([parsed_news, roberta_df], axis=1) #将两者按照行来concat(也就是从下边)
        parsed_news.to_csv(target, sep='\t', index=False)  #存储到target到csv文件

        pd.DataFrame(category2int.items(),   #将category2int存储
                     columns=['category', 'int']).to_csv(category2int_path,
                                                         sep='\t',
                                                         index=False)
        print(
            f'Please modify `num_categories` in `src/config.py` into 1 + {len(category2int)}'
        )

        pd.DataFrame(word2int.items(), columns=['word',
                                                'int']).to_csv(word2int_path,
                                                               sep='\t',
                                                               index=False)
        print(
            f'Please modify `num_words` in `src/config.py` into 1 + {len(word2int)}'
        )

        pd.DataFrame(entity2int.items(),
                     columns=['entity', 'int']).to_csv(entity2int_path,
                                                       sep='\t',
                                                       index=False)
        print(
            f'Please modify `num_entities` in `src/config.py` into 1 + {len(entity2int)}'
        )

    elif mode == 'test': #如果是test模式, 
        category2int = dict(pd.read_table(category2int_path).values.tolist())
        # na_filter=False is needed since nan is also a valid word
        word2int = dict(
            pd.read_table(word2int_path, na_filter=False).values.tolist())
        #需要将值转为list
        entity2int = dict(pd.read_table(entity2int_path).values.tolist())

        parsed_news = news.swifter.apply(parse_row, axis=1)  #parse_new同样应用到news上
        parsed_news = pd.concat([parsed_news, roberta_df], axis=1)
        parsed_news.to_csv(target, sep='\t', index=False)

    else:
        print('Wrong mode!')

def generate_word_embedding(source, target, word2int_path)

def generate_word_embedding(source, target, word2int_path):
    """
    Generate from pretrained word embedding file
    If a word not in embedding file, initial its embedding by N(0, 1)  #创建Embedding
    Args:
        source: path of pretrained word embedding file, e.g. glove.840B.300d.txt
        target: path for saving word embedding. Will be saved in numpy format
        word2int_path: vocabulary file when words in it will be searched in pretrained embedding file
    """
    # na_filter=False is needed since nan is also a valid word
    # word, int
    word2int = pd.read_table(word2int_path, na_filter=False, index_col='word')
    source_embedding = pd.read_table(source,  #单词嵌入式表示
                                     index_col=0,
                                     sep=' ',
                                     header=None,
                                     quoting=csv.QUOTE_NONE,
                                     names=range(config.word_embedding_dim))
    # word, vector
    source_embedding.index.rename('word', inplace=True) #原单词嵌入的索引重命名为word
    # word, int, vector
    merged = word2int.merge(source_embedding,   #单词的合并,采用交集方式; 左index和右index都是True
                            how='inner',
                            left_index=True,
                            right_index=True)
    merged.set_index('int', inplace=True)   #重新设置index,并且不保留原来的

    missed_index = np.setdiff1d(np.arange(len(word2int) + 1),   #在atr1中而不在atr2中(也就是缺失的数组)
                                merged.index.values)
    missed_embedding = pd.DataFrame(data=np.random.normal(
        size=(len(missed_index), config.word_embedding_dim)))
    missed_embedding['int'] = missed_index
    missed_embedding.set_index('int', inplace=True)

    final_embedding = pd.concat([merged, missed_embedding]).sort_index()
    np.save(target, final_embedding.values)

    print(
        f'Rate of word missed in pretrained embedding: {(len(missed_index)-1)/len(word2int):.4f}'
    )

def transform_entity_embedding(source, target, entity2int_path):

def transform_entity_embedding(source, target, entity2int_path):
#将实体的embedding转化为numpy格式
    """
    Args:
        source: path of embedding file
        target: path of transformed embedding file in numpy format
        entity2int_path
    """
    entity_embedding = pd.read_table(source, header=None)  #读入soure,没有列名!
    entity_embedding['vector'] = entity_embedding.iloc[:,
                                                       1:101].values.tolist()
    #将列名从0变为entity                                    
    entity_embedding = entity_embedding[[0, 'vector']].rename(columns={0: "entity"})

    entity2int = pd.read_table(entity2int_path)
    merged_df = pd.merge(entity_embedding, entity2int,
                         on='entity').sort_values('int')
    #这里是将某个词的向量变为随机值!   可以看到np.random.normal(size = (n个, d维度))             
    entity_embedding_transformed = np.random.normal(
        size=(len(entity2int) + 1, config.entity_embedding_dim))
    for row in merged_df.itertuples(index=False):   #将某些列设置为正常值
        entity_embedding_transformed[row.int] = row.vector
    np.save(target, entity_embedding_transformed)   #这样就形成了转换后的实体

main()函数

def parse_behaviors(source, target, user2int_path):
    """
    Parse behaviors file in training set.
    Args:
        source: source behaviors file
        target: target behaviors file
        user2int_path: path for saving user2int file
    """

def parse_news(source, target, roberta_output_dir, category2int_path,
               word2int_path, entity2int_path, mode):
    """
    Parse news for training set and test set
    Args:
        source: source news file
        target: target news file
        if mode == 'train':
            category2int_path, word2int_path, entity2int_path: Path to save
        elif mode == 'test':
            category2int_path, word2int_path, entity2int_path: Path to load from
"""
def generate_word_embedding(source, target, word2int_path):
    """
    Generate from pretrained word embedding file
    If a word not in embedding file, initial its embedding by N(0, 1)  #创建Embedding
    Args:
        source: path of pretrained word embedding file, e.g. glove.840B.300d.txt
        target: path for saving word embedding. Will be saved in numpy format
        word2int_path: vocabulary file when words in it will be searched in pretrained embedding file
"""

def transform_entity_embedding(source, target, entity2int_path):
#将实体的embedding转化为numpy格式
    """
    Args:
        source: path of embedding file
        target: path of transformed embedding file in numpy format
        entity2int_path
    """


if __name__ == '__main__':
    train_dir = './data/train'
    val_dir = './data/val'
    test_dir = './data/test'

	# 下面都是相同的,都是处理原数据,之后再使用glove来进行
    print('Process data for training')
    # 第一步: training (只是使用glove词典)
    # 先处理好用户行为、以及news的数字化处理! 同时形成用于glove和roberta的数据格式
    print('Parse behaviors')
    parse_behaviors(path.join(train_dir, 'behaviors.tsv'),
                    path.join(train_dir, 'behaviors_parsed.tsv'),
                    path.join(train_dir, 'user2int.tsv'))   #

    print('Parse news')
    parse_news(path.join(train_dir, 'news.tsv'),
               path.join(train_dir, 'news_parsed.tsv'),
               path.join(train_dir, 'roberta'),
               path.join(train_dir, 'category2int.tsv'),
               path.join(train_dir, 'word2int.tsv'),
               path.join(train_dir, 'entity2int.tsv'),
               mode='train')
	# 形成我们的单词向量嵌入
    print('Generate word embedding')
    generate_word_embedding(
        f'./data/glove/glove.840B.{config.word_embedding_dim}d.txt',
        path.join(train_dir, 'pretrained_word_embedding.npy'),
        path.join(train_dir, 'word2int.tsv'))
	
	# 形成实体嵌入
    print('Transform entity embeddings')
    transform_entity_embedding(
        path.join(train_dir, 'entity_embedding.vec'),
        path.join(train_dir, 'pretrained_entity_embedding.npy'),
        path.join(train_dir, 'entity2int.tsv'))
	
	# 第二步: 验证(使用我们的roberta)因为后面是需要进行微调roberta的!
    print('\nProcess data for validation')

    print('Parse news')
    parse_news(path.join(val_dir, 'news.tsv'),
               path.join(val_dir, 'news_parsed.tsv'),
               path.join(val_dir, 'roberta'),
               path.join(train_dir, 'category2int.tsv'),
               path.join(train_dir, 'word2int.tsv'),
               path.join(train_dir, 'entity2int.tsv'),
               mode='test')
	
	#第三步:测试(同样使用我们的roberta)
    print('\nProcess data for test')
	
	
    print('Parse news')
    parse_news(path.join(test_dir, 'news.tsv'),
               path.join(test_dir, 'news_parsed.tsv'),
               path.join(test_dir, 'roberta'),
               path.join(train_dir, 'category2int.tsv'),
               path.join(train_dir, 'word2int.tsv'),
               path.join(train_dir, 'entity2int.tsv'),
               mode='test')

补充:

1. getattr()函数

  • 描述
    getattr() 函数用于返回一个对象属性值

  • 语法
    getattr(object, name[, default])

  • 参数
    object – 对象。
    name – 字符串,对象属性。
    default – 默认返回值,如果不提供该参数,在没有对应属性时,将触发 AttributeError

  • 返回值
    返回对象属性值

  • 实例

>>>class A(object):
...     bar = 1
... 
>>> a = A()
>>> getattr(a, 'bar')        # 获取属性 bar 值
1
>>> getattr(a, 'bar2')       # 属性 bar2 不存在,触发异常
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'bar2'
>>> getattr(a, 'bar2', 3)    # 属性 bar2 不存在,但设置了默认值
3
>>>

实例2:

>>> class A(object):        
...     def set(self, a, b):
...         x = a        
...         a = b        
...         b = x        
...         print a, b   
... 
>>> a = A()                 
>>> c = getattr(a, 'set')
>>> c(a='1', b='2')
2 1
>>> 

实际的实例:

try:
    config = getattr(importlib.import_module('config'), f"{model_name}Config")
except AttributeError:
    print(f"{model_name} not included!")
    exit()

2. importlib.import_module()

这样做的目的就是为了动态的引入模块!

import importlib
 
params = importlib.import_module('b.c.c') #绝对导入  在同一文件夹下则不同b了
params_ = importlib.import_module('.c.c',package='b') #相对导入

3. f-strings 字符串格式化

这种在字符串前面加“f”就相当于 “XX{ }”.format(model_name)
举例:

name = '宝元'
age = 18
sex = '男'
msg1 = F'姓名:{name},性别:{age},年龄:{sex}'  # 大写字母也可以
msg = f'姓名:{name},性别:{age},年龄:{sex}'   # 建议小写
print(msg)

4. pd.read_table()

原代码中是header和names混合使用! 如果header = None; names就该设置列明

今天遇到个小坑,在这里记录一下。 当你用read_csv读文件的时候,如果文本里包含英文双引号,直接读取会导致行数变少或是直接如下报错停止 Error tokenizing data. C error: EOF inside string starting at row 1

在这里插入图片描述

quoting=3或是quoting=csv.QUOTE_NONE”

5. fillna()函数

具体请参考博文

我只摘录和原代码相关的内容!
该函数用来填充缺失值! 也就是NaN!

  • inplace: 方法有改变原文件也有不改变原文件两种方式! 不改变原文件顾名思义也就是创建临时对象,只有在运行程序时有一个对象,相反,则是把原文件改了! 该
  • 填充值
#二、指定inplace参数
 
print (df1.fillna(0,inplace=True))
print ("-------------------------")
print (df1)

使用0来填充,那么源代码就是使用" " 空格来填充

6. split()方法

  • 描述:
    str.split() 通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则分隔 num+1 个子字符串

  • 语法:

split() 方法语法:

str.split(str="", num=string.count(str)).
  • 参数:
    str – 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
    num – 分割次数。默认为 -1, 即分隔所有。(从第一个分隔符开始切分)

  • 返回值
    返回分割后的字符串列表。(list列表)

  • 实例

>>>str = "Line1-abcdef \nLine2-abc \nLine4-abcd";
>>>print str.split( );       # 以空格为分隔符,包含 \n,如果为空的话,那么就是所有空字符
>>>print str.split(' ', 1 ); # 以空格为分隔符,分隔成两个

['Line1-abcdef', 'Line2-abc', 'Line4-abcd']
['Line1-abcdef', '\nLine2-abc \nLine4-abcd']
  • 实例2
    以下实例以 # 号为分隔符,指定第二个参数为 1,返回两个参数列表。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
txt = "Google#Runoob#Taobao#Facebook"
 
# 第二个参数为 1,返回两个参数列表
x = txt.split("#", 1)
 
print x

7. iteritems()、 iterrows()、itertuples():

itertuples()

博客
这是将原DataFrame转成一行一行的tuple,也就是小DataFrame!
如果我们想访问要和getattr结合!

举例:
假如原test是这样的!

当我们运行itertuples()时:

其它的请看链接,我暂时不需要

8. pd.DataFrame()

也就是创建DataFrame()
DataFrame是由多种类型的列构成的二维标签数据结构.[1]
往往包含index(行标签)columns(列标签), 彼此独立, 互不影响
直观理解:DataFrame 是带标签的二维数组
所以问题在于如何创建DataFrame:

最普通的创建DataFrame

原文博客

DataFrame()函数的参数index的值相当于行索引,若不手动赋值,将默认从0开始分配。columns的值相当于列索引,若不手动赋值,也将默认从0开始分配。

data = {
        '性别':['男','女','女','男','男'],
        '姓名':['小明','小红','小芳','大黑','张三'],
        '年龄':[20,21,25,24,29]}
df = pd.DataFrame(data, index=['one','two','three','four','five'],
               columns=['姓名','性别','年龄','职业'])
df
df.values 返回ndarray类型的对象

ndarray类型即numpy的 N 维数组对象,通常将DataFrame类型的数据转换为ndarray类型的比较方便操作。如对DataFrame类型进行切片操作需要df.iloc[ : , 1:3]这种形式,对数组类型直接X[ : , 1:3]即可。

X = df.values
print(type(X)) #显示数据类型
X

运行结果:

<class 'numpy.ndarray'>
[['小明' '男' 20 nan]
 ['小红' '女' 21 nan]
 ['小芳' '女' 25 nan]
 ['大黑' '男' 24 nan]
 ['张三' '男' 29 nan]]
df.iloc[ 行序,列序 ] 按序值返回元素
df.iloc[1,1]
Index(['one', 'two', 'three', 'four', 'five'], dtype='object')
df.at[index, columns]

作用:获取某个位置的值,例如获取第0行,第a列的值,即:index=0, columns = ‘a’
data = df.at[0, ‘a’]

9. items()

描述

Python 字典(Dictionary) items() 函数以列表返回可遍历的(键, 值) 元组数组

语法

dict.items()

参数

返回值

返回可遍历的(键, 值) 元组数组 (不是list,而是数组)

实例

#!/usr/bin/python
# coding=utf-8
 
dict = {'Google': 'www.google.com', 'Runoob': 'www.runoob.com', 'taobao': 'www.taobao.com'}
 
print "字典值 : %s" %  dict.items()
 
# 遍历字典列表
for key,values in  dict.items():
    print key,values
字典值 : [('Google', 'www.google.com'), ('taobao', 'www.taobao.com'), ('Runoob', 'www.runoob.com')]
Google www.google.com
taobao www.taobao.com
Runoob www.runoob.com

10. .to_csv()

原文博客

1.首先查询当前的工作路径:

import os
os.getcwd() #获取当前工作路径

2.to_csv()是DataFrame类的方法,read_csv()是pandas的方法

dt.to_csv() #默认dt是DataFrame的一个实例,参数解释如下
  • 路径 path_or_buf: A string path to the file to write or a StringIO
dt.to_csv('Result.csv') #相对位置,保存在getwcd()获得的路径下
dt.to_csv('C:/Users/think/Desktop/Result.csv') #绝对位置
  • 分隔符 sep : Field delimiter for the output file (default ”,”)
dt.to_csv('C:/Users/think/Desktop/Result.csv',sep='?')#使用?分隔需要保存的数据,如果不写,默认是,
  • 替换空值 na_rep: A string representation of a missing value (default ‘’)
dt.to_csv('C:/Users/think/Desktop/Result1.csv',na_rep='NA') #确实值保存为NA,如果不写,默认是空
  • 是否保留行索引 index: whether to write row (index) names (default True)
dt.to_csv('C:/Users/think/Desktop/Result1.csv',index=0) #不保存行索引
  • 是否保留列名 header: Whether to write out the column names (default True)
dt.to_csv('C:/Users/think/Desktop/Result.csv',header=0) #不保存列名
  • 是否保留某列数据 cols: Columns to write (default None
dt.to_csv('C:/Users/think/Desktop/Result.csv',columns=['name']) #保存索引列和name列

11. tpdm(iterator)

Tqdm 是一个快速,可扩展的Python进度条,可以在 Python 长循环中添加一个进度提示信息,用户只需要封装任意的迭代器 tqdm(iterator)。
使用pip就可以安装。

  • 参数:
iterable=None,  当然是我们要被迭代的对象!  迭代多少次,则显示多少         
desc=None,      传入str类型,作为进度条标题(类似于说明)
total=None,     预期的迭代次数
leave=True,             
file=None, 
ncols=None,         可以自定义进度条的总长度
mininterval=0.1,    最小的更新间隔
maxinterval=10.0,   最大更新间隔
miniters=None, 
ascii=None, 
unit='it',
unit_scale=False,
dynamic_ncols=False,
smoothing=0.3,
bar_format=None, 
initial=0,
position=None, 
postfix             以字典形式传入 详细信息 例如  速度= 10
  • 操作1:
from tqdm import tqdm
 
for i in tqdm(range(10000)):
     """一些操作"""
     pass

在这里插入图片描述

操作2:

dict = {"a":123,"b":456}
for i in tqdm(range(10),total=10,desc = "WSX",ncols = 100,postfix = dict,mininterval = 0.3):
     pass

在这里插入图片描述

操作3

from tqdm import trange
from random import random, randint
from time import sleep
with trange(100) as t:
    for i in t:
        # Description will be displayed on the left
        t.set_description('下载速度 %i' % i)
        # Postfix will be displayed on the right,
        # formatted automatically based on argument's datatype
        t.set_postfix(loss=random(), gen=randint(1,999), str='详细信息',
                     lst=[1, 2])
        sleep(0.1)

在这里插入图片描述
其中trange(i) 是 tqdm(range(i)) 的简单写法

13. x.endwith()

Python endswith() 方法用于判断字符串是否以指定后缀结尾,如果以指定后缀结尾返回True,否则返回False。可选参数"start"与"end"为检索字符串的开始与结束位置。

endswith()方法语法:

str.endswith(suffix[, start[, end]])

14. iter(object)

用于生成迭代对象,之后采用next()来访问它的每一个内容!
意义和for循环是一样的! 只不是可能是为了方便统一访问吧!

15. DataFrame.explode(self, column: Union[str, Tuple])

将类似列表的每个元素转换为一行,从而复制索引值。

  • 参数
    column : str或tuple

-返回值
DataFrame
将列表分解为子列的行;将为这些行复制索引。

  • Raises:
    ValueError:
    如果框架的列不是唯一的。

  • 举例

>>> df = pd.DataFrame({'A': [[1, 2, 3], 'foo', [], [3, 4]], 'B': 1})
>>> df
           A  B
0  [1, 2, 3]  1
1        foo  1
2         []  1
3     [3, 4]  1
>>> df.explode('A')
     A  B
0    1  1
0    2  1
0    3  1
1  foo  1
2  NaN  1
3    3  1
3    4  1

可以看到list中每个元素单独成为了一行! 行名和列名都保留

16. pandas之dropna()

该函数主要用于滤除缺失数据。
如果是Series,则返回一个仅含非空数据和索引值的Series,默认丢弃含有缺失值的行。

xx.dropna()

对于DataFrame:

data.dropna(how = 'all')    # 传入这个参数后将只丢弃全为缺失值的那些行
data.dropna(axis = 1)       # 丢弃有缺失值的列(一般不会这么做,这样会删掉一个特征)
data.dropna(axis=1,how="all")   # 丢弃全为缺失值的那些列
data.dropna(axis=0,subset = ["Age", "Sex"])   # 丢弃‘Age’和‘Sex’这两列中有缺失值的行    

17. pandas中的reset_index()

数据清洗时,会将带空值的行删除,此时DataFrame或Series类型的数据不再是连续的索引,可以使用reset_index()重置索引。

只有一个参数drop = True! 默认是False!
drop = False: 会保留原来不连续的索引成为新的一列!
drop = True: 会删除原来的索引

18. df[[‘name’]] 和 df[‘name’]

df.groupby(['key1','key2'])[['data2']].mean()
Out[27]: 
              data2
key1 key2          
a    one   0.072958
     two  -0.962946
b    one   0.946299
     two   1.576233

若对需要聚合的单列使用单中括号,则输出时不会带有列标签,末尾会单独输出一行属性列

df.groupby(['key1','key2'])['data2'].mean()
Out[29]: 
key1  key2
a     one     0.072958
      two    -0.962946
b     one     0.946299
      two     1.576233
Name: data2, dtype: float64

若需要将多列进行聚合时,单中括号和双中括号没有区别

df.groupby(['key1','key2'])['data1','data2'].mean()
Out[31]: 
              data1     data2
key1 key2                    
a    one   0.018737  0.072958
     two  -1.319022 -0.962946
b    one   0.917741  0.946299
     two  -1.288477  1.576233
df.groupby(['key1','key2'])[['data1','data2']].mean()
Out[30]: 
              data1     data2
key1 key2                    
a    one   0.018737  0.072958
     two  -1.319022 -0.962946
b    one   0.917741  0.946299
     two  -1.288477  1.576233

19. pandas中的map()

通过df.(tab)键,发现df的属性列表中有apply() 和 applymap(),但没有map().
map()是python 自带的方法, 可以对df某列内的元素进行操作

20. Roberta

Roberta是基于Bert的这是毋庸置疑的! 它的API
它的论文地址

它建立在BERT的基础上,修改了关键的超参数,去掉了next-sentence预训练目标,并使用更大的小批量和学习率进行训练。

论文摘要如下:

语言模型前训练已经带来了显著的成绩提高,但仔细比较不同的方法是具有挑战性的。训练在计算上很昂贵,通常是在不同大小的私有数据集上进行的,而且,正如我们将展示的,超参数选择对最终结果有重大影响。我们提出了一项BERT训练前复制研究(Devlin et al., 2019),仔细衡量了许多关键超参数和训练数据大小的影响。我们发现BERT明显缺乏训练,并且可以匹配或超过在它之后发布的每个模型的性能。我们最好的模型在GLUE, RACE和SQuAD上实现了最先进的结果。这些结果突出了以前被忽视的设计选择的重要性,并提出了关于最近报道的改进的来源的问题。我们发布我们的模型和代码。

Robertmodel (robustly Bert Model)其实就是加强版的bertmodel
具体只有以下几点的改变

1:pretraining 得数据从普通bert模型的16g 变成了160g

2.去除掉了nsp,也就是不做next sentence prediction

3.使用的动态mask,普通bert用的是静态mask,
区别就是静态mask,对于一个句子,mask掉部分词,塞进模型,训练完后,就换下一 句,而动态mask会多重复几次,每次都mask掉不同的词

4.training的过程使用更长的句子

技巧:

  • 该实现与BertModel相同,只是进行了微小的嵌入调整,并为Roberta预先训练的模型进行了设置。
  • RoBERTa具有与BERT相同的体系结构,但使用字节级BPE作为标记器(与GPT-2相同),并使用不同的预训练方案。
  • RoBERTa没有token_type_ids,您不需要指明哪个令牌属于哪个段。只需用分离token分离您的段。tokenizer.sep_token(或< / s >)
  • CamemBERT 是 RoBERTa的外皮。使用示例请参见此页。
    该模型由julien-c贡献。可以在这里找到原始代码。

后面两者先进行前者后进行后者

RobertaTokenizer

class transformers.RobertaTokenizer(vocab_file, merges_file, errors=‘replace’,
bos_token=’< s {s} s>’, eos_token=’< / s {/s} /s>’, sep_token=’< / s {/s} /s>’, cls_token=’< s {s} s>’, unk_token=’< / u n k {/unk} /unk>’, pad_token=’< / p a d {/pad} /pad>’, mask_token=’< / m a s k {/mask} /mask>’, add_prefix_space=False, **kwargs)

使用字节级字节对编码构造一个RoBERTaTokenizer,该标记赋予器派生自GPT-2标记赋予器。
这个标记赋予器已经被训练成将空格视为标记的一部分(有点像句子片段),所以无论单词是否在句子的开头(没有空格),它都将被不同的编码:

from transformers import RobertaTokenizer
tokenizer = RobertaTokenizer.from_pretrained("roberta-base")
tokenizer("Hello world")['input_ids']
#[0, 31414, 232, 328, 2]
tokenizer(" Hello world")['input_ids']
#[0, 20920, 232, 2]

您可以通过在实例化这个标记赋予器或在某些文本上调用它时传递add_prefix_space=True来绕过该行为,但由于模型不是以这种方式预先训练的,它可能会导致性能下降。
注意:
当与is_split_into_words=True一起使用时,这个标记赋予器将在每个单词前添加一个空格(甚至是第一个)。
这个标记器继承了PreTrainedTokenizer,它包含了大部分的主要方法。用户应该参考这个超类以获得关于这些方法的更多信息。

RobertaConfig和RobertModel

class transformers.RobertaConfig(pad_token_id=1, bos_token_id=0, eos_token_id=2, **kwargs)[SOURCE]

这是用于存储RobertaModel或TFRobertaModel配置的配置类。它用于根据指定的参数实例化RoBERTa模型,定义模型体系结构。
配置对象继承自PretrainedConfig,可用于控制模型输出。更多信息请阅读PretrainedConfig的文档。
RobertaConfig类直接继承了BertConfig。它重用相同的默认值。请查看父类了解更多信息。
举例:

from transformers import RobertaConfig, RobertaModel

# Initializing a RoBERTa configuration
configuration = RobertaConfig()

# Initializing a model from the configuration
model = RobertaModel(configuration)

# Accessing the model configuration
configuration = model.config
参数:
  • vocab_file(str) - 词汇表文件的路径。
  • merges_file (str) -合并文件的路径。
  • errors(str, optional, defaults to “replace”) -更多信息请参见bytes.decode。
  • bos_token (str, optional, defaults to “< s {s} s>”) -在预训练期间使用的序列标记的开始。可以使用序列分类器标记。
    Note:
    当使用特殊标记构建序列时,这不是用于序列开始的标记。使用的令牌是cls_token。
  • eos_token(str, optional, defaults to “<{/s}>”)
    序列标记的结束。
  • sep_token (str, optional, defaults to “<{/s}>”)
    分隔符,用于从多个序列构建序列,例如用于序列分类的两个序列,或用于文本和用于问答的一个问题。它也被用作由特殊标记构建的序列的最后一个标记。
  • cls_token (str, optional, defaults to “< s {s} s>”)
    在进行序列分类时使用的分类器标记(对整个序列进行分类,而不是对每个标记进行分类)。当使用特殊标记构建时,它是序列的第一个标记。
  • unk_token (str, optional, defaults to “< u n k {unk} unk>”)
    未知的令牌。不在词汇表中的令牌不能转换为ID,而是被设置为这个令牌。
  • pad_token(str, optional, defaults to “< p a d {pad} pad>”)
    用于填充的令牌,例如对不同长度的序列进行批处理时。
  • mask_token(str, optional, defaults to “”)
    用于屏蔽值的令牌。这是在使用掩码语言建模训练此模型时使用的令牌。这就是模型将要尝试预测的标记。
  • add_prefix_space(bool, optional, defaults to False)
    是否向输入添加初始空间。这样就可以像对待其他单词一样对待引导词。(RoBERTa标记器通过前面的空格检测单词的开头)。
函数

build_inputs_with_special_tokens()
通过连接和添加特殊标记,从序列或序列对构建用于序列分类任务的模型输入。RoBERTa序列的格式如下:
create_token_type_ids_from_sequences()
从传递给序列对分类任务的两个序列创建掩码。RoBERTa不使用令牌类型id,因此返回一个零列表。
get_special_tokens_mask()
从没有添加特殊标记的标记列表中检索序列id。当使用标记器prepare_for_model方法添加特殊标记时,将调用此方法。
save_vocabulary()
只保留标记赋予者的词汇表(词汇表+添加的标记)。
此方法不会保存标记赋予器的配置和特殊标记映射。使用_save_pretrained()保存标记赋予器的整个状态。

21. Tokenizer 统一使用

https://blog.csdn.net/claroja/article/details/108365064

主要是使用tokenizer,首先会分割文本成单词(tokens),然后将这些单词转换为数字。
在 pretraining or fine-tuning一个model时,使用from_pretrained()来处理文本

from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained('bert-base-cased')

encoded_input = tokenizer("Hello, I'm a single sentence!")
print(encoded_input)  #输出的是字典! 
{'input_ids': [101, 138, 18696, 155, 1942, 3190, 1144, 1572, 13745, 1104, 159, 9664, 2107, 102],
 'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]}

返回的是一个字典!

tokenizer可以接收列表。

通过参数可以给句子设定:
1.长度不够的句子,添加pad(padding=True)
2.超出长度的句子,截取truncate(truncation=True)
3.返回tensor(return_tensors=‘pt’)

22. Path().mkdir(parents=True, exist_ok=True)

该Path是pathlib模块中的! 不是os中的!
在介绍Python安全创建目录之前,先举一个不安全创建目录的方式:

if not os.path.exists(directory):
    os.makedirs(directory)

在例子里,先判断目录是否存在,然后创建目录。这种方式是不安全的,它会导致竞争条件。在os.path.exists()和os.makedirs()之间的时间可能会出现目录被创建。不推荐使用这种方式。

Python 3.5+:
在python 3.5+可以使用pathlib的mkdir:

import pathlib
pathlib.Path('/my/directory').mkdir(parents=True, exist_ok=True) 

pathlib的mkdir接收两个参数:

parents:如果父目录不存在,是否创建父目录。
exist_ok:只有在目录不存在时创建目录,目录已存在时不会抛出异常

23. torch.no_grad()

禁用梯度计算的上下文管理器。

当您确定不会调用Tensor.backward()时,禁用梯度计算对推理很有用。 它将减少计算所需的内存消耗,否则requires_grad=True。

在这种模式下,每次计算的结果都有requires_grad=False,即使输入是requires_grad=True。

这个上下文管理器是线程本地的; 它不会影响其他线程的计算。

也可作为装饰器。 (确保用括号实例化。)

24. math.ceil()

math.ceil() 返回大于整数的最小整数值,如果number已经是整数了那么就是相同的数
代码:

# Python code to demonstrate the working of ceil() 
    
# importing "math" for mathematical operations  
import math  
    
x = 33.7
    
# returning the ceil of 33.7 
print ("The ceil of 33.7 is:", end ="")  
print (math.ceil(x))
输出: The ceil of 33.7 is:34

代码2:

# Python code to demonstrate the working of ceil() 
    
# importing "math" for mathematical operations  
import math  
    
# prints the ceil using ceil() method  
print ("math.ceil(-13.1):", math.ceil(-13.1)) 
print ("math.ceil(101.96):", math.ceil(101.96))
math.ceil(-13.1): -13
math.ceil(101.96): 102

25. **dict()

d1 = {
‘name’: ‘jim’,
‘age’: 18
}

d2 = {**d1,
‘color’: ‘yellow’
}

print(d2)
在这里插入图片描述

26. Bert、RoBerta的输入输出

输入
输出

  • last_hidden_state:shape是(batch_size, sequence_length, hidden_size),hidden_size=768,它是模型最后一层输出的隐藏状态
  • pooler_output:shape是(batch_size, hidden_size),这是序列的第一个token(classification token)的最后一层的隐藏状态,它是由线性层和Tanh激活函数进一步处理的,这个输出不是对输入的语义内容的一个很好的总结,对于整个输入序列的隐藏状态序列的平均化或池化通常更好。
  • hidden_states:这是输出的一个可选项,如果输出,需要指定config.output_hidden_states=True,它也是一个元组,它的第一个元素是embedding,其余元素是各层的输出,每个元素的形状是(batch_size, sequence_length, hidden_size)
  • attentions:这也是输出的一个可选项,如果输出,需要指定config.output_attentions=True,它也是一个元组,它的元素是每一层的注意力权重,用于计算self-attention heads的加权平均值

27 ’ '.join(str)

描述

将序列中的元素以指定的字符连接生成一个新的字符串。

语法

语法: ‘sep’.join(seq)
参数说明:
sep:分隔符。可以为空
seq:要连接的元素序列、字符串、元组、字典

返回值

返回通过指定字符连接序列中元素后生成的新字符串。

>>> a="abcd"
>>> ",".join(a)
'a,b,c,d'

>>> "|".join(['a','b','c'])
'a|b|c'

>>> ",".join(('a','b','c'))
'a,b,c'

28. swifter()

目前我在网上找到的pandas加速包有两个:modin和swifter
modin 宣称"通过更改一行代码来加速你的pandas工作流",官方文档https://github.com/modin-project/modin
swifter 对apply函数加速,官方文档https://github.com/jmcarpenter2/swifter

29. merge()

本篇详细说明merge的应用,join 和concatenate的拼接方法的与之相似。

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
         left_index=False, right_index=False, sort=True,
         suffixes=('_x', '_y'), copy=True, indicator=False,
         validate=None)

参数如下:

  • left: 拼接的左侧DataFrame对象
  • right: 拼接的右侧DataFrame对象
  • on: 要加入的列或索引级别名称。 必须在左侧和右侧DataFrame对象中找到。 如果未传递且left_index和right_index为False,则DataFrame中的列的交集将被推断为连接键。
  • left_on:左侧DataFrame中的列或索引级别用作键。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
  • right_on: 左侧DataFrame中的列或索引级别用作键。 可以是列名,索引级名称,也可以是长度等于DataFrame长度的数组。
  • left_index: 如果为True,则使用左侧DataFrame中的索引(行标签)作为其连接键。 对于具有MultiIndex(分层)的DataFrame,级别数必须与右侧DataFrame中的连接键数相匹配。
  • right_index: 与left_index功能相似。
  • how: One of ‘left’, ‘right’, ‘outer’, ‘inner’. 默认inner。inner是取交集,outer取并集。比如left:[‘A’,‘B’,‘C’];right[’'A,‘C’,‘D’];inner取交集的话,left中出现的A会和right中出现的另一个A进行匹配拼接,如果没有是B,在right中没有匹配到,则会丢失。'outer’取并集,出现的A会进行一一匹配,没有同时出现的会将缺失的部分添加缺失值。
  • sort: 按字典顺序通过连接键对结果DataFrame进行排序。 默认为True,设置为False将在很多情况下显着提高性能。
  • suffixes: 用于重叠列的字符串后缀元组。 默认为(‘x’,’ y’)。
  • copy: 始终从传递的DataFrame对象复制数据(默认为True),即使不需要重建索引也是如此。
  • indicator:将一列添加到名为_merge的输出DataFrame,其中包含有关每行源的信息。 _merge是分类类型,并且对于其合并键仅出现在“左”DataFrame中的观察值,取得值为left_only,对于其合并键仅出现在“右”DataFrame中的观察值为right_only,并且如果在两者中都找到观察点的合并键,则为left_only。

30. setdiff1d

属于numpy!

一、函数解释

setdiff1d(ar1, ar2, assume_unique=False)

1.功能:找到2个数组中集合元素的差异。

2.返回值:在ar1中但不在ar2中的已排序的唯一值。

3.参数:

ar1:array_like 输入数组。
ar2:array_like 输入比较数组。
assume_unique:bool。如果为True,则假定输入数组是唯一的,即可以加快计算速度。 默认值为False。

二、具体示例

1.assume_unique = False的情况:

   a = np.array([1,2,3])
    b = np.array([4,5,6])
    c = np.setdiff1d(a, b)
    print(c)#[1 2 3]
    a = np.array([1,2,3])
    b = np.array([1,2,3])
    c = np.setdiff1d(a, b)
    print(c)#[]
    a = np.array([1,2,3])
    b = np.array([2,3,4])
    c = np.setdiff1d(a, b)
    print(c)#[1]
    a = np.array([1,2,3,4])
    b = np.array([3,4,5,6])
    c = np.setdiff1d(a, b)
    print(c)#[1 2]
    a = np.array([1,2,3,2,4,1])
    b = np.array([3,4,5,6])
    c = np.setdiff1d(a, b)
    print(c)#[1 2]
    a = np.array([8,2,3,2,4,1])
    b = np.array([7,4,5,6,3])
    c = np.setdiff1d(a, b)
    print(c)#[1 2 8]

可以从最后看出返回的值从小到大排序,并且唯一。(8在a的第1位,2在a中重复了2次)

2.assume_unique = True的情况:

a = np.array([3,2,1])
b = np.array([4,5,6])
c = np.setdiff1d(a, b,True)
print(c)#[3 2 1]
a = np.array([8,2,3,2,4,1])
b = np.array([7,4,5,6,3])
c = np.setdiff1d(a, b,True)
print(c)#[8 2 2 1]
a = np.array([8,2,3,4,2,4,1])
b = np.array([7,9,5,6,3])
c = np.setdiff1d(a, b,True)
print(c)#[8 2 4 2 4 1]

可以看出把在a中的但是不在b中的元素按a中的顺序排序,并且不合并重复的元素,即假定输入数组也是唯一的,因此相比于False确实提升了运算速度。

31. df.rename()

df.rename()用于更改行列的标签,即行列的索引。可以传入一个字典或者一个函数。在数据预处理中,比较常用。

官方文档:

DataFrame.rename(self, mapper=None, index=None, columns=None, axis=None, copy=True, inplace=False, level=None, errors=‘ignore’)

参数实例:

import pandas as pd 
df = pd.DataFrame({'name':['zhao','qian','sun','wang'],'mark':[150,122,155,132],'gender':['female','female','male','male']})
df

	name	mark	gender
0	zhao	150		female
1	qian	122		female
2	zhou	155		male
3	wang	132		male
  1. mapper:dict or function
    映射关系,可以是字典,也可以是一个函数。
df.rename({0:111})
	name	mark	gender
111	zhao	150		female #行索引从0变为111
1	qian	122		female
2	zhou	155		male
3	wang	132		male

df.rename(lambda x: x+11) #参数也可以是函数,索引都加了11
	name	mark	gender
11	zhao	150		female
12	qian	122		female
13	zhou	155		male
14	wang	132		male

2 index、columns、axis
这3个参数作用类似,dataframe中有行和列两个方向,在改名时,需要指明改名的是行还是列(默认是行),使用df.rename(index = mapper)或者df.rename(columns=mapper)的形式,和

df.rename(mapper,axis=0 or 1)的效果是一样的
df.rename(lambda x: x+'11',axis=1)
	name11	mark11	gender11  #列索引都加了11,name变为name11
0	zhao	150		female
1	qian	122		female
2	zhou	155		male
3	wang	132		male

df.rename(columns=lambda x: x+'11')#等价于上面,写法更简洁直观
	name11	mark11	gender11
0	zhao	150		female
1	qian	122		female
2	zhou	155		male
3	wang	132		male
  1. copy:bool,default = True
    默认为True,效果不清楚。。。文档就一句话,与会复制底层数据(also copy underlying data), 等一个课代表解答一下。
  2. inplace:bool,default False
    将结果返回赋值给原变量,无需再次将结果赋值给新变量。即df.rename(inplace=True)之后,df的值发生改变(pandas中好多方法都有这个参数,此处就演示了)

32.Bert和Glove

https://blog.csdn.net/weixin_37735081/article/details/94361265

  1. 词向量模型
    词向量模型包括:word2vec、glove、fastText、elmo、GPT和bert、xlnet等。
    这里面有些是“一揽子”表示的词向量模型,如word2vec、glove,是用一个固定的向量来表示一个具体的token(单词)。这样的好处是简单且易于使用,预训练完词向量之后可以直接通过查“词典”来使用,但是缺点也很明显,比如一词多义怎么办?一个token只有一个固定的向量。
    另一些则是需要在句子中才能将词向量具体化,比如bert和xlnet。这样词向量就不是一个具体的词向量了,在不同的语境中一个单词可以有不同的意思。缺点是比较消耗资源,太贵。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值