这段时间,会有系列真实的竞赛项目陪伴,我会通过修炼笔记的方式记录我这段时间学习数据竞赛的经历,希望每个竞赛都能给我们带来收获和成长! 这个故事会很长,但我会坚持往下走,你看,天上太阳正晴,如果可以,我们一起吧…

1. 写在前面

终于下定决心涉足这个纠结很久的话题了,作为一个懵懂无知的竞赛小白,其实是非常渴望参加一场数据比赛的,因为数据比赛对于AIer来说真的很重要,不知道你是否遇到过这样的一些疑惑,就是涉足一个新领域的时候,比如数据挖掘,先非常努力的花时间学习python,numpy,pandas,scipy,sklearn这些基础知识,但是当后面真的遇到实际问题的时候,却不知道如何下手去分析,再回头想掏之前学会的工具时,发现这些工具依然在,但已记不清它们的使用说明。难不成之前学习过的这些都白学了? 其实不是的,这些工具都在,只不过我们之前没有真正的去用过它, 所以,比赛就是一个让我们大展身手的舞台,通过解决实际问题,我们才能真正掌握之前的工具,也是学习知识的一个融合,毕竟解决实际问题,需要各个领域的知识交融和碰撞。在这个过程中,我们还可以认识一些志同道合的伙伴,一起进步和交流,进行思维的碰撞并得到成长。

所以这个数据竞赛修炼系列我会把我的所思所学都记录下来并分享,一是因为解决问题的思路可以迁移和变换,这样或许会帮助更多的人,二是通过整理和总结,可以使得知识和技能在自己脑海中逗留的时间长一些吧。

首先声明这个系列的每一篇都会很长,并且会有一大波代码来袭,毕竟每一篇都是一个完整的数据竞赛,每一篇都需要很长的时间消化整理,因为我想用最朴素,最详细的语言把每个比赛的思路和代码说给你听。

今天是数据竞赛修炼笔记的第一篇,带来的比赛是2018年科赛网上的一个比赛快手用户活跃度的预测,我们拿到了一份快手平台记录的关于快手用户的30天一个行为数据集(记录用户注册,登录,视频观看与发布,互动的记录),我们的目标就是根据这个行为数据集预测在未来七天的活跃用户。
首先我们会对任务的目标和数据进行分析,然后会概览模型的架构,从模型的角度提取特征和标签构建数据集,然后基于tensorflow建立模型并训练得到结果。最后会再结合一些好的解决方案,对解决这个问题的思路和知识点进行总结。

大纲如下:

  • 任务目标与数据分析
  • 整理模型架构
  • 构建用户特征,生成汇总表
  • 制作标签
  • 建立模型并训练,得到最后的结果
  • 知识点和思路的总结(两个知识点温习:pandas的iterrows()和groupby())

Ok, let’s go!

开始之前,需要导入包:

import numpy as np
import pandas as pd
import tensorflow as tf
from deep_tools import f
from deep_tools import DataGenerator

2. 任务目标和数据分析

在这一部分,我们先看看拿到的是一份什么样的数据,然后分析一下我们这个任务到底怎么应该去做。

我们会拿到四个表格,分别是:

  • 用户注册日志表,记录的是用户什么时候使用什么方式(微信,qq)什么设备(手机,pad)进行注册的快手账号,会有四个字段的信息,注意,day这一列,由于我们搜集的是30天的数据,所以这里的取值是1-30, 表示的是用户第几天的行为,后面那几份数据也是一样。
  • APP启动日志表,记录的是用户在第几天登录过快手app, 两个字段的信息
  • 视频创建日志表, 记录的是用户在第几天创作过视频
  • 用户行为日志表,这个比较关键,也是我们后面制作特征的主要渠道来源,由用户的行为才能看出用户是不是活跃

    下面,我们就导入数据,详细的看一下这些数据吧
"""读取数据集"""
register = pd.read_csv('user_register_log.txt', sep='\t', names=['user_id', 'register_day', 'register_type', 'device_type'])
launch = pd.read_csv('app_launch_log.txt', seq='\t', names=['user_id', 'launch_day'])
create = pd.read_csv('video_create_log.txt', seq='\t', names=['user_id', 'create_day'])
activity = pd.read_csv('user_activity_log.txt', seq='\t', names=['user_id', 'act_day', 'page', 'video_id', 'author_id', 'act_type'])

通过上面的四行代码,我们就可以把txt的数据读入并转成了pd的DataFrame格式,注意上面的分隔符要制定成\t。然后我们看其中一个表里面是什么样的数据。这是记录用户行为的表(其他的类似):

接下来,我们对数据和任务进行一个解析。

  • 关于数据
    我们拿到的是一个连续的30天之内用户的一个行为数据,包含了四个数据集,分别记录用户的注册,登录,创建视频,使用行为的信息, 但是有一个问题要注意,就是不一定每个用户的信息都是30天的记录,因为,我们这里有一个注册信息表,里面有一个register_day的字段,这个字段不一定所有用户都是1,即不一定每个用户都是在第一天进行注册的。比如,假设一个用户在第七天才注册的,那么前七天就没有这个用户的信息,假设一个用户是在第25天注册的,那么这个用户只有后五天的数据。 所以这是这个任务的一个难点所在,就是每个用户的被记录的时间序列长度并不是一样的, 所有后面我们分析的时候,对于一个用户,得先分析是在哪一天注册的,我们再从这一天开始去算。
  • 关于任务
    我们拿到了每个用户的这样的数据,是要预测未来的活跃度,注意这个未来,不是接下来的一两天,而是挺长的一段时间,一个周期这样的。我们这里是预测未来七天内的, 比如有个用户第七天注册了,我们预测的是他第七天到第十四天的活跃度的可能性。这就是我们的目标,基于之前的一段序列数据,来预测未来七天的活跃度的可能性。这很明显,是一个时间序列的预测任务

理解了数据和任务,下面我们可以考虑如何去解决这个问题,注意这样的实际项目可能和我们那种kaggle的入门赛还不一样,那样的问题一上来就直接给定好了数据特征和标签之类的东西,我们做的是特征工程,然后建立模型解决就可以了。
而这种实际问题上,给定的数据不可能拿来直接用,得需要我们自己提取特征和标签。 但是我们目前可能看到这些数据之后一脸懵逼,不知道如何下手分析,那么我们不妨换一种思路,从模型入手,看看什么样的模型适合这种问题,然后倒推出针对这种模型,我们应该给他一个什么样的输入。这样,我们再去做相应的输入出来,这也是考虑问题的一种方式吧。 所以这次先从模型开始。

3. 整体模型架构

关于模型的问题,我们做的虽然说预测用户的活跃度,但可以转化成一个二分类的问题,最后输出就是未来七天时间内,这个用户是否活跃(0或者1)。既然是二分类的问题,那么这里的模型选择就比较多了,什么xgb,lgb,这些优秀的机器学习算法都可以,但是我们分析一下,我们最后拿到的这个数据应该是针对某一个用户,会有从他注册到后面行为的一系列信息,而这些都是时间上进行相关的,比如一个用户第七天注册了,那么我们就有这个用户第七天到第30天的各种行为,也是一种时间序列的预测。关于这种时间序列的预测,如果要使用机器学习的方式,就需要用滑动窗口去切割数据集,并且特征提取上需要使用历史信息的统计特征。

我们这里使用神经网络的方式,也就是RNN来完成这个任务,这样不需要对输入序列做过多处理,也不使用滑动窗口。毕竟时间的监督学习任务,RNN还是比较擅长的,能够捕捉到时间的这种关联信息。

使用RNN,一般地会想到如下解决方案:

以几天内的用户行为序列为输入,以未来七天该用户是否活跃为标签,标注该序列。这是一种Many2One的解决方案。但是这样做的话为了充分利用数据,需要对训练数据做大量的滑窗,以实现数据增广,计算成本高。另外,每个序列只有一个标签,梯度难以传导,导致训练困难。所以我们可以考虑Many2Many结构,即每个输入都对应输出之后7天是否活跃,充分利用监督信息,减轻梯度传到负担,使训练更加容易。我们就可以构建出RNN的大体模型长这样:

这样我们的网络架构就构思出来了,但是这里还有一个细节,就是序列是变长的,就是用户的记录天数是不同的,每个batch中取相同长度的序列,不同batch长度不同,每次随机取某一长度的batch。这时候我们需要使用动态RNN,根据时间序列的长度自己调整。

有了网络架构,那么我们怎么去构建数据呢? 我们知道网络上面的都是一些label值,也就是0或者1的这些,表示活跃不活跃。 下面的序列就是我们的输入数据,但是t1,t2,…tn这些数据应该是长什么样子呢?

下面就是这个问题的核心工作: 构建用户特征,也就是我们的输入应该是什么样子的。

4. 构建用户特征序列

这一块是我们的重点,我们想一下,既然网络的输入是时间序列,那么肯定输入的数据有一个维度是时间,那么我们不妨这样,对于每一个用户,我们找一下他的信息和时间有什么关联。很容易就会想到,如果一个用户注册了,那么从注册之后的每一天,快手都会记录他每一天的行为(是不是登录,是不是点赞,创建视频等),那么我们可以这样,每一个用户给他建立一个二维的表,表的每一行代表注册后快手记录他的每一天, 每一列代表每一天干的事情。 我们根据所给的表格提取出这些相应的信息,那么每个用户的特征序列其实就构建完毕了。 所以根据这样的一个思路,我们可以构建特征出来。步骤如下:

  1. 保存每个用户的记录数据
    既然之前我们说过,每个用户的记录序列长度是不一样子的,所以这个地方我们应该首先先统计每个用户到底有几天的记录数据,把这个长度我们先保存下来。这个就是我们上面说的那个二维表的行数,这个比较简单,直接用总天数减去他注册的时间就可以啦。

    """计算序列长度: 持续时间 = 数据总时间 - 注册时间"""
    register['seq_length'] = 31 - register['register_day']
    register.head()
    

    可以看一下这个注册信息表对了一列长度信息(不一定都是30):

  2. 创建用户记录字典
    根据前面的记录天数,创建一个字典,来存储不同记录天数的用户到底有哪些, key表示记录长度,value表示用户id。

    比如只有1天记录的有哪些用户,2天记录的有哪些,…30天完整记录的用户有哪些),这个的目的就是因为我们的用户序列都不等长,也就是每个用户的记录天数不一定一样,这样就导致如果统一喂入神经网络的话,没法组成一个矩阵的形式, 但如果根据记录天数把用户给分开了,那么同一个记录天数下会有很多用户,这些序列是等长的, 那么我们就可以把这些划分成一个batch给神经网络,就好处理了。就是网络的输入接收的每个batch的序列长度要求是相同的,但是不同batch的序列可以不同。

    方式也很简单,建立一个空字典键是1-30天,然后遍历一遍register表,根据最后一列的seq_length, 把对应的user_id填到相应的天数中,这样这个字典就保存了每一个不同天数下都哪些用户了。

    """根据前面的记录天数,创建一个字典,来存储不同记录天数的用户到底有哪些 """
    user_queue = {i: []  for i in range(1,31)}for index, row in register.iterrows():  # 这个iterrows是对DataFrame进行行遍历,是在数据框中的行进行迭代的一个生成器,它返回每行的索引及一个包含行本身的对象。user_queue[row[-1]].append(row[0]) # row[-1]是seq_length, row[0]是user_id
    
  3. 接下来,构建用户特征
    这一块,我们得考虑究竟怎么去提取特征呢? 首先,得有一个特征的个数,就是针对每个用户,每天的记录,我们得提取多少个特征。 这些特征就是用户的行为,比如什么时候登陆,登陆之后,点没点赞,创没创建视频这些东西(都从数据集里面提取)。 所以对于一个用户来说,我们的输入数据最后应该是一个矩阵,每一行代表着记录的天数,每一列代表一个特征,看下面的图也知道为什么之前要统计不同记录对应的用户了吧,每个用户对应一个矩阵,然后很多个用户合起来就是一个3维的向量,这一个至少是一个立方体的形式。 如果用户的记录不一样的话,就没法进行用户的合并,所以我们这里有了这样一个字典之后,我们就可以把每个记录的用户看成一个batch放入神经网络了。

    这一块的思路呢? 我们是要构建用户特征,所以我们定义一个用户序列的类,把所有相关的操作都放到用户序列的里面

    """定义一个user_seq类"""
    class user_seq:def __init__(self, register_day, seq_length, n_features):"""register_day: 用户第几天进行的登录seq_length: 用户序列的长度,就是记录了几天登录信息, 行数n_features: 每天提出的特征个数, 列数"""self.register_day = register_dayself.seq_length = seq_lengthself.array = np.zeros([seq_length, n_features])   # 这就是上面那个用户对应的矩阵形式,初始化位0self.page_rank = np.zeros([self.seq_length])self.pointer = 1# 提取特征填入特征矩阵def put_feature(self, feature_number, string):for i in string.split(','):pos, value = i.split(':')     # 注册后的第几天进行了登录,1为指示符self.array[int(pos)-self.register_day, feature_number] = 1   # 从注册后开始记录def get_array(self):return self.array# 得到标签  如果一个用户在未来七天活跃了,那么标记为1def get_label(self):self.label = np.array([None] * self.seq_length)    # 一个seq_length长度的数组active = self.array[:, :12].sum(axis=1)          # 这里选了一部分特征做了个sum,意思是不管是转发,登录,啥的,只要做了就算一次活动for i in range(self.seq_length-7):      # 这地方得控制一下,如果一个用户15-30的数据,那么我们标签最多只能到23天,因为30天之后的数据我们没有self.label[i] = 1 * (np.sum(active[i+1:i+8]) > 0)    # 这里对于当前的i,如果未来七天内活跃过,那么标签就是1return self.label
    
    1. 首先,会构建出每个用户的特征矩阵,就是上面的那种矩阵构建出来,初始化为0, 这里假设特征列为15,即f=15

      """创建用户的记录矩阵"""
      n_features = 15
      data = {row[0]:user_seq(register_day=row[1], seq_length=row[-1], n_feagures=n_features) for index, row in register.iterrows()}
      

      这样,每一个用户就都会用了一个二维特征表

    2. 遍历上面的数据表,开始提取相应的特征,把这些特征填入相应用户的相应记录的相应特征中
      这一块,就是基于之前的数据表提取特征,分为下面几块提取

      • 用户的登录信息特征(launch表)
        这一块就是每个用户在某天是否登录, 先看一下launch表

        下面提取特征, 填入到用户的二维表:
        launch[‘launch_freq’] = 1
        launch_table = launch.groupby([‘user_id’, ‘launch_day’], as_index=False).agg({‘launch_freq’:‘sum’})
        然后, 根据用户的id进行整合一下,把相同用户的结果放在一起(代码中有个recode_to_sequence(table)函数)
        launch_table = record_to_sequence(launch_table)
        结果是下面这样:

        接下来,就是把这个登录的信息填入到特征矩阵,是否登录作为第一个特征
        for index, row in launch_table.iterrows(): # 根据登录信息对用户特征表进行填充
           data[row[0]].put_feature(0, row[1])

      后面的这几个提取特征和第一个思路一样,具体见代码,都是先根据id和特征分组统计,然后相同id的合并,然后添入特征矩阵。

      • 用户创作视频的信息特征(create表)
      • 用户使用时的行为特征,例如点赞,转发等(activity表的act_type)
      • 用户产生行为的界面信息特征(activity表的page字段)
      • 用户观看其他用户的行为特征(activity表的author_id字段 != user_id)
      • 观看自己作品的行为特征(activity表的author_id字段 == user_id)

      由于这块的代码篇幅太长,所以这里只讲大体思路,至于上面的代码都放入了GitHub,后面会给出链接。

5. 制作数据标签

通过上面的操作,我们就构建好了神经网络的输入,当然这里这样构建特征是为神经网络服务的,如果是想用机器学习的一些方式,就可以提取一些统计的特征,比如平均值,方差,中位数的这些东西用xgb什么的跑,但是这种时间之间的特征可能就捕捉不到了。

下面,我们就是制作数据的标签了: 在未来七天内是否会使用APP, 这个的思路就是对用户从注册开始就进行统计,对于每1天的数据展开,如果其未来七天内这个用户活跃过,就标记为1

label = {user_id:user.get_label() for user_id, user in data.items()}

这里用到了user_seq类汇总的git_label函数,这个函数做了个这样的事情:首先建立了一个用户记录等长的数组,然后用户二维表的每一天的活动进行了求和,然后从注册的第一天开始遍历,如果未来七天有一天有活动,那么标签为1,否则为0
最后会得到一个这样的结果:

最后一句:

data = {user_id: user.get_array() for user_id, user in data.items()}

这样data是一个字典,键是1-30的某一天,对应的值是3维的矩阵(好多用户,每个用户的二维表)

这样特征被标签就构建完毕。 下面就是建立动态RNN模型进行训练测试了。

6. 建立模型并且训练

通过上面的方式,我们已经把数据特征和标签都已经制作完毕,接下来就是建立RNN模型进行训练了,这里使用tensorflow来建立模型。

6.1 合并上述的提取方法,通过数据生成器获得

这一块就是把上面的方法写到了deep_tools里面,用DataGenerator就可以获得最终的结果了。

register=pd.read_csv('user_register_log.txt',sep='\t',names=['user_id','register_day','register_type','device_type'])
launch=pd.read_csv('app_launch_log.txt',sep='\t',names=['user_id','launch_day'])
create=pd.read_csv('video_create_log.txt',sep='\t',names=['user_id','create_day'])
activity=pd.read_csv('user_activity_log.txt',sep='\t',names=['user_id','act_day','page','video_id','author_id','act_type'])data_generator=DataGenerator(register,launch,create,activity)

6.2 构建RNN网络模型并进行训练

前面说过,这里由于每个batch的时间序列长度可能不一样,所以需要使用动态RNN,单元GRU和LSTM效果差不多,都可以

n_features = 12
n_hu = 8
with tf.variable_scope('train'):     # tf.variable_scope用来指定变量的作用域# 变量与输入lr = tf.placeholder(tf.float32, [], name='learning_rate')    # 定义学习率# 隐藏层到输出层的参数w, b    w_shape(n_hu,1)   b_shape(1)  n_huWie隐藏单元的个数W_out = tf.get_variable('W_out', [n_hu, 1])   b_out = tf.get_variable('b_out', [1])# x和y  x_shape(batch_size, seq_length, n_features)x = tf.placeholder(tf.float32, [None, None, n_features])y = tf.placeholder(tf.float32, [None, None])# batch_size和seq_length的大小batch_size = tf.shape(x)[0]seq_length = tf.shape(x)[1]# RNN 层cell = tf.nn.rnn_cell.GRUCell(n_hu)     # n_hu表示每个GRUcell里面的单元个数initial_state = cell.zero_state(batch_size, dtype=tf.float32)   # 指定初识状态,因为之前没有训练过outputs, state = tf.nn.dynamic_rnn(cell, x, initial_state=initial_state)  # 使用的动态Rnn# outputs(batch_size, max_seq_length, n_hu)     这是所有时间步的输出# state (batch_size, n_hu)   这是最后一个时间步的输出# 具体:https://blog.csdn.net/u010960155/article/details/81707498# 输出层outputs = tf.reshape(outputs, [-1, n_hu])    # (batch_size*max_seq_length, n_hu)logits = tf.matmul(outputs, W_out) + b_out    # (batch_size*max_seq_length)logits = tf.reshape(logits, tf.stack([batch_size, seq_length]))

这里选择部分预测结果与标签当做训练损失的计算,这个由于比赛已经结束,没法进行线上训练,所以只能线下训练,选择前16天进行训练,16-23天测试

# 选择部分预测结果与标签当做训练损失计算
logits_local_train = logits[:, :-14] # 这里-14或者是更小,因为本地训练,我们用前16天训练,16-23天测试。
label_local_train = y[:, :-14]

设置训练选项, 加入正则化,Adam优化算法

# 设置损失函数# 正则化项
regularizer = tf.contrib.layers.l2_regularizer(0.00001)
penalty = tf.contrib.layers.apply_regularization(regularizer, tf.trainable_variables())obj_local = tf.losses.sigmoid_cross_entropy(label_local_train, logits_local_train) + penalty
optimizer = tf.train.AdamOptimizer(lr)
set_local = optimizer.minimize(obj_local)# 选择部分预测结果与标签当做测试损失计算
logits_local_test = logits[:, -8]
label_local_test = y[:, -8]   #  这里也可以选择其他的天

训练函数:

def train(n_obs=1000, step=1000, lr_feed=0.01):#date_seq = [31] + list(range(2, 16)) + [16] * 15variables = [set_local, obj_local, label_local_train, logits_local_train]for i in range(step):length, id_list, data_x, data_y = data_generator.next_batch(n_obs)_, los, lab, log = sess.run(variables, feed_dict={x:data_x, y:data_y, lr:lr_feed})

这里训练这个,取数据的思路得解释一下:next_batch操作这里取数据的时候,这个序列长度并不是随机取的。 如果看next_batch函数的时候就会注意到, 首先是先有了local_random_list, 然后从这里面取序列的长度, 那么这个local_random_list做了个什么事情呢? 他不是1-30的序列长度随机选,因为不同序列长度的用户个数不一样,而大部分应该集中在15天及以后,1-14天的那种用户可能很少,这样就有可能不够一个batch_size。 所以尽量的选15天以后的,这个local_random_list里面的元素就是从15开始,然后越往后的元素个数越多,那么相应被选择的几率就越大。 这样无非就是选择序列的时候,对应的用户让他多一些,这样好取够batch_size。

然后有了这个序列长度,我们就可以取相应的用户了,pointer指针就是为了从头开始选择用户数据,够一个batch_size为止,如果超了用户数目的长度,就回到头上,然后打乱用户数据,再取。 (这里建议看一下代码,只描述可能不知道咋回事, 在deep.tools.py)
然后就是训练了:

sess = tf.Session()
sess.run(tf.global_variables_initializer())train(n_obs=1000, step=2000, lr_feed=0.01)

6.3 模型测试并输出结果

比赛使用的f1值进行评估, 关于f1值可以查看算法模型评估之混淆矩阵,accuracy,查准率,查全率,AUC(ROC)等小总结:

测试函数

def test():n_NA = 14     # 本地训练, 我们是1-16天训练,16-23天预测,所以这个地方最大是30-14# 优化目标和数据variables_1 = [obj_local, logits_local_train, label_local_train]variables_2 = [logits_local_test, label_local_test]obs_count, cum_loss, correct = 0, 0, 0user, prob, real = [], [], []# 训练损失for length, id_list, data_x, data_y in zip(*data_generator.get_set('train')):_obj, _logits_train, _label_train = sess.run(variables_1,feed_dict={x:data_x, y:data_y, lr:0.001})obs_count += (length - n_NA) * len(id_list)cum_loss += _obj * (length - n_NA) * len(id_list)correct += np.sum((1 * (_logits_train>0) == _label_train))# 测试损失for length, id_list, data_x, data_y in zip(*data_generator.get_set('test')):_ = sess.run(variables_2, feed_dict={x:data_x, y:data_y, lr:0.001})_logits_test, _label_test = _real += list(_label_test)user += list(id_list)prob += list(1 / (1+np.exp(-_logits_test.reshape([-1]))))# 打印训练损失print('train_loss', cum_loss/obs_count)# 测试损失result = pd.DataFrame({'user_id':user, 'prob':prob, 'label':real})print('test_score:', f(result))return resulttest()

最终结果如下:

会输出最终的f1值和一个表,这个表里面就是给定id,预测未来七天是否活跃的结果。

6.4 余弦退火 + 热重启训练思想

这里顺带记录一个训练的技巧:

越来越接近loss值的全局最小值时,学习率应该变得越来越小来使得模型尽可能接近最小值。 然后突然提高学习率,来“跳出”局部最小值并找到通向全局最小值的路径。

def cos_annealing_local(epoch=5):all_result=Nonefor i in range(epoch):train(step=2000,lr_feed=0.01)train(step=2000,lr_feed=0.001)result=test()print(sess.run(penalty))result.columns=['label','prob%s'%i,'user_id']if i==0:all_result=resultelse:all_result=pd.merge(all_result,result)return all_result

这个效果会提升一点。

7. 知识点和思路的总结

关于知识点的总结这块,这次我们在处理特征的时候用的最多的是pandas的DataFrame的行遍历iterrows和groupby函数,所以重点总结一下这两个函数的使用,但是由于篇幅原因,写到了另外一篇博客里面https://blog.csdn.net/wuzhongqiang/article/details/104714458

而关于思路这块,这个比赛方案的思路是一个接近top的一个方案。所以感觉人家的想法还是很不错的,至少我第一次拿到这个题目一脸懵逼,所以这一块还得多学习。

简单总结一下: 我们这次做的是一个快手用户活跃度的预测,可以看做一个二分类的问题,针对这个预测问题,首先,我们从构建网络的整体结构出发,去倒推我们的输入是什么样子,根据网络结构,我们把用户的特征以二维表的形式构建,每一行代表时间,每一列代表特征(行为活动),这样就可以取提取特征,得到最终的训练数据。 对于变长序列,我们采用了动态RNN的方式建立网络,然后取batch的时候,我们选择的序列长度是其包含的数据尽量的多一些。 关于训练,我们这里get到了一种叫做余弦退火热重启的思想。 最后我们还知道了线上训练和线下训练还是有些区别的。

关于这个比赛的详细代码和笔记,我已经放到了GitHub上,可以自行查阅:
https://github.com/zhongqiangwu960812/AIGame/tree/master/GameOfKesci

数据竞赛修炼笔记之快手用户活跃度的预测相关推荐

  1. JData大数据竞赛18年赛题-如期而至-用户购买时间预测

    年前做的,也是学习别人的作品作为记录 一.赛题 表1:sku基本信息表(jdata_sku_basic_info) 表2:用户基本信息表(jdata_user_basic_info) 表3:用户行为表 ...

  2. CCF大数据竞赛-面向电信行业存量用户的智能套餐个性化匹配模型

    题目:面向电信行业存量用户的智能套餐个性化匹配模型(2018 CCF-大数据竞赛(联通研究院举办) ) 网址:https://www.datafountain.cn/competitions/311/ ...

  3. 【数据竞赛】CCF乘用车细分市场销量预测竞赛总结

    题目:乘用车细分市场销量预测 类型:时序回归 https://datafountain.cn/competitions/352/ 赛题背景 近几年来,国内汽车市场由增量市场逐步进入存量市场阶段,201 ...

  4. 大数据工程师修炼笔记

    想要成为大数据工程师?你需要掌握以下知识(上) 文| 林肯公园(拒绝任何不标明来源的转载) 国际数据公司IDC预测,到2020年,企业基于大数据计算分析平台的支出将突破5000亿美元,大数据解决方案在 ...

  5. 2022年第三届MathorCup 大数据竞赛 赛道B 北京移动用户体验影响因素研究 完整建模方案及代码实现详解

    北京移动用户体验影响因素研究 移动通信技术飞速发展,给人们带来了极大便利,人们也越来越离不开移动通信技术带来的各种便捷.随着网络不断的建设,网络覆盖越来越完善.各个移动运营商,越来越重视客户的网络使用 ...

  6. 预测不了世界杯比分,就预测百威啤酒销量,送数据竞赛冠军笔记

    Part.01丨赛题背景 组织方:微软加速器 上海站真实数据来源:百威英博(命题,并提供脱敏的业务数据) 提出三个问题: 1.库存需求预测 2.销售数量预测 3.经销商违规行为检测 数据大致的情况-- ...

  7. 如何预测百威啤酒销量?数据竞赛冠军笔记分享 思路

    转载: http://dy.163.com/v2/article/detail/DHALCA3N0511VFT2.html 赛题背景 组织方:微软加速器 真实数据来源:几家顶级快消品牌 上海站:百威英 ...

  8. 数据竞赛实战(3)——公共自行车使用量预测

    前言 1,背景介绍 公共自行车低碳,环保,健康,并且解决了交通中"最后一公里"的痛点,在全国各个城市越来越受欢迎.本次练习的数据取自于两个城市某街道上的几处公共自行车停车桩.我们希 ...

  9. 【大数据竞赛】2022MathorCup大数据挑战赛 B题 北京移动用户体验影响因素研究 题目分析

    系列文章目录 第一章 [大数据竞赛]2022MathorCup大数据竞赛 B题 北京移动用户体验影响因素研究 题目分析 第二章[大数据竞赛]2022MathorCup大数据挑战赛 B题 北京移动用户体 ...

  10. 【大数据竞赛】2022MathorCup大数据挑战赛 B题 北京移动用户体验影响因素研究 探索性数据分析

    系列文章目录 第一章 [大数据竞赛]2022MathorCup大数据竞赛 B题 北京移动用户体验影响因素研究 题目分析 第二章[大数据竞赛]2022MathorCup大数据挑战赛 B题 北京移动用户体 ...

最新文章

  1. 【原创】VSFTP: Login failure: 530 Login incorrect的解决办法
  2. 【Android 逆向】ART 脱壳 ( InMemoryDexClassLoader 脱壳 | InMemoryDexClassLoader 类加载器脱壳点总结 )
  3. C# 如果何从线程中操作控件
  4. 用zookeeper来实现分布式锁
  5. MongoDB中的分页–如何真正避免性能下降?
  6. 计算机优秀大学生,应届计算机业优秀大学生的自我鉴定
  7. phpstudy安装及简单使用教程
  8. 个人信息安全规范----3、个人信息的收集、存储、使用
  9. 可以打印快递电子面单的表格
  10. cmd指令ie打开html文件,命令行调用 IE 浏览器打开指定网址
  11. C#类库推荐 拼多多.Net SDK,开源免费!
  12. Excel如何将某个特定值变为空值
  13. js-禁止微信内置浏览器调整字体大小
  14. “无实物尝百味”通过控制微电流刺激产生味觉—1.硬件设计篇
  15. 2022.7.11~8.1纪中游记
  16. MG动画实例——旋转的地球
  17. python二维数组去重复_python 去除二维数组/二维列表中的重复行方法
  18. 采购经理如何快速熟悉工作流程
  19. 基于微信小程序的二手汽车拍卖系统
  20. C++单例模式与线程安全

热门文章

  1. 每日案例(第五期):智慧金融11-12 | 知识图谱实践案例集(速读版)
  2. 《西部世界》第三季开播,机器人会比人类更有人性吗?
  3. 计算机参数怎么写,format命令的怎样写 format命令的格式和参数【详解】
  4. Keil 5报错error C216: subscript on non-array or too many dimensions
  5. struts2配置细节
  6. js获取不同时区时间
  7. 【Day4.1】打的士去卧佛寺
  8. 磁盘被写保护无法使用怎么办?
  9. excel导出时报错 “文件格式和扩展名不匹配,文件可能已损坏或不安全”解决办法
  10. 元学习(Meta Learning)最全论文、视频、书籍资源整理