ICME 2019短视频内容理解与推荐竞赛正式启动(附baseline方法)

2019 年 2 月 19 日 PaperWeekly


想到推荐算法,大家可能会想到电商和游戏。不过,随着短视频产品的崛起,推荐算法也迎来一个新的风口,被大量应用在短视频领域,吸引更多的用户看到自己喜欢的内容。 


2019 年 2 月,ICME 2019 短视频内容理解与推荐竞赛正式开放提交。本次比赛挂靠多媒体领域的顶会 IEEE ICME,主题为预测用户是否看完及点赞一个短视频。 


比赛链接:


https://biendata.com/competition/icmechallenge2019/ 


比赛奖金:2 万美元 


时间:2019 年 2 月 11 日 – 2019 年 4 月 7 日



背景


“一图胜千言”,仅仅一张图片就包含大量信息,难以用几个词来描述。更不用说短视频了。所以,虽然机器学习近年来在图像识别、语音识别等领域取得了重大进步,但在视频内容理解领域仍有许多问题需要探索。 


不过,目前也有不少相关研究。2016 年,谷歌 YouTube 团队在 ACM RecSys  会议上发表论文 Deep Neural Networks for YouTube Recommendations,详细介绍了不少 YouTube 视频推荐功能的技术细节。


比赛数据与赛道


为了方便大家参赛,ICME 2019 短视频内容理解与推荐竞赛的主办方已经提取出了多种类型的短视频内容特征,包括视觉特征、文本特征和音频特征。 


此外,为了方便不同背景的参赛者参加比赛,本次比赛按照数据量分成两个赛道(数据格式和预测任务都相同): 


赛道 1:大规模数据集,亿级别的数据信息。 


赛道2:小规模数据集,千万级别的数据信息。


评测方法


参赛选手需要预测测试数据中每一条数据的点击(finish+like)概率。本次比赛使用 AUC(ROC 曲线下面积)作为评估指标。AUC 越高,代表结果越优,排名越靠前。在总分中,finish 和 like 的分配比例是:0.7*finish+0.3*like。


Baseline代码


在 TRACK 2 上,baseline 的结果分别为 like:86.5%,finish:69.8%。 


Baseline 需要 TensorFlow 1.12.0。模型下载地址:


https://github.com/challenge-ICME2019-Bytedance/Bytedance_ICME_challenge


baseline脚本 & 代码说明

#——运行脚本——#
train.sh  

#——训练模型——#
train.py  

#——模型参数输入——#
common/  
model_args.py  

#——tensorflow数据转换输入——#
data_io/  
data_parser.py  

#——模型准备与框架搭建——#
models/  
model.py  

#——fm推荐算法——#
model_zoo/  
fm.py

#--utils数据处理——#
utils/  
utils.py


Bytedance_ICME_challenge/model_zoo/fm.py


import tensorflow as tf
 
class FMModelParams(object):
  """初始化fm模型权重"""
  def __init__(self, feature_size, embedding_size):
    self._feature_size = feature_size
    self._embedding_size = embedding_size
 
  def initialize_weights(self):
    """ 初始化fm权重
    Returns
    weights:
      feature_embeddings:  vi, vj second order params
      weights_first_order: wi first order params
      bias: b  bias
    """

 
    weights = dict()
    weights_initializer=tf.glorot_normal_initializer()
    bias_initializer=tf.constant_initializer(0.0)
    weights["feature_embeddings"] = tf.get_variable(
        name='weights',
        dtype=tf.float32,
        initializer=weights_initializer,
        shape=[self._feature_size, self._embedding_size])
    weights["weights_first_order"] = tf.get_variable(
        name='vectors',
        dtype=tf.float32,
        initializer=weights_initializer,
        shape=[self._feature_size, 1])
    weights["fm_bias"] = tf.get_variable(
        name='bias',
        dtype=tf.float32,
        initializer=bias_initializer,
        shape=[1])
    return weights
 
class FMModel(object):
  """fm实施"""
 
  @staticmethod
  def fm_model_fn(features, labels, mode, params):
    """建立tensorflow模型"""
 
    #解析参数
    embedding_size = params['embedding_size']
    feature_size = params['feature_size']
    batch_size = params['batch_size']
    learning_rate = params['learning_rate']
    field_size = params['field_size']
    optimizer_used = params['optimizer']
 
    #解析特征
    feature_idx = features["feature_idx"]
    feature_idx = tf.reshape(feature_idx, shape=[batch_size, field_size])
    labels = tf.reshape(labels, shape=[batch_size, 1])
    feature_values = features["feature_values"]
    feature_values = tf.reshape(feature_values, shape=[batch_size, field_size, 1])
 
    # tensorflow fm 权重
    tf_model_params = FMModelParams(feature_size, embedding_size)
    weights = tf_model_params.initialize_weights()
    embeddings = tf.nn.embedding_lookup(
        weights["feature_embeddings"],
        feature_idx
        )
    weights_first_order = tf.nn.embedding_lookup(
        weights["weights_first_order"],
        feature_idx
        )
    bias = weights['fm_bias']
 
    #构建函数
    ##first order
    first_order = tf.multiply(feature_values, weights_first_order)
    first_order = tf.reduce_sum(first_order, 2)
    first_order = tf.reduce_sum(first_order, 1, keepdims=True)
 
    ##second order
    ### feature * embeddings
    f_e_m = tf.multiply(feature_values, embeddings)
    ###  square(sum(feature * embedding))
    f_e_m_sum = tf.reduce_sum(f_e_m, 1)
    f_e_m_sum_square = tf.square(f_e_m_sum)
    ###  sum(square(feature * embedding))
    f_e_m_square = tf.square(f_e_m)
    f_e_m_square_sum = tf.reduce_sum(f_e_m_square, 1)
 
    second_order = f_e_m_sum_square - f_e_m_square_sum
 
    second_order = tf.reduce_sum(second_order, 1, keepdims=True)
 
    ##最终目标函数
    logits = second_order + first_order + bias
    predicts = tf.sigmoid(logits)
 
    ##损失函数
    sigmoid_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=logits, labels=labels)
    sigmoid_loss = tf.reduce_mean(sigmoid_loss)
    loss = sigmoid_loss
 
    #训练操作
    if optimizer_used == 'adagrad':
      optimizer = tf.train.AdagradOptimizer(
          learning_rate=learning_rate,
          initial_accumulator_value=1e-8)
    elif optimizer_used == 'adam':
      optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
    else:
      raise Exception("unknown optimizer", optimizer_used)
 
    train_op = optimizer.minimize(loss, global_step=tf.train.get_global_step())
 
 
    #计算auc
    eval_metric_ops = {
        "auc": tf.metrics.auc(labels, predicts)
        }
    predictions = {"prob": predicts}
 
    return tf.estimator.EstimatorSpec(
        mode=tf.estimator.ModeKeys.TRAIN,
        predictions=predicts,
        loss=loss,
        eval_metric_ops=eval_metric_ops,
        train_op=train_op)


Bytedance_ICME_challenge/models/model.py


""" import necessary packages"""
import tensorflow as tf
from data_io.data_parser import PosShifts, LineParser
from model_zoo.fm import FMModel
 
 
class RecommendModelHandler(object):
  """设定推荐模型的类"""
  def __init__(self, train_dataset_path, val_dataset_path, save_model_dir,  \
      learning_rate=0.1, num_threads=1, num_epochs=100, batch_size=40,  \
      embedding_size=100, optimizer='adam', task="finish", track=2)
:

    """初始化基本参数"""
    self._learning_rate = learning_rate
    self._num_threads = num_threads
    self._num_epochs = num_epochs
    self._batch_size = batch_size
    self._train_dataset_path = train_dataset_path
    self._val_dataset_path = val_dataset_path
    self._save_model_dir = save_model_dir
    self._embedding_size = embedding_size
    self._optimizer = optimizer
    self._task = task
    self._track = track
 
 
  def build_model(self):
    """建立推荐模型框架"""
    config = tf.estimator.RunConfig().replace(
        session_config=tf.ConfigProto(device_count={'CPU':self._num_threads}),
        log_step_count_steps=20)
    PosShifts(self._track)
    feature_size = PosShifts.get_features_num()
    params={
        'feature_size': feature_size,
        'embedding_size': self._embedding_size,
        'learning_rate': self._learning_rate,
        'field_size'5,
        'batch_size': self._batch_size,
        'optimizer': self._optimizer}
 
    model = tf.estimator.Estimator(
        model_fn=FMModel.fm_model_fn,
        model_dir=self._save_model_dir,
        params=params,
        config=config)
    return model
 
  def prepare_data_fn(self, data_mode='train'):
    """准备训练/验证数据"""
    if data_mode == 'train':
      dataset = tf.data.TextLineDataset(self._train_dataset_path)
    elif data_mode == 'val':
      dataset = tf.data.TextLineDataset(self._val_dataset_path)
    else:
      raise Exception("unknown data_mode", data_mode)
 
    if self._task == "finish":
      dataset = dataset.map(LineParser.parse_finish_line)
    elif self._task == "like":
      dataset = dataset.map(LineParser.parse_like_line)
    else:
      raise Exception("unknown task", task)
 
    dataset = dataset.shuffle(buffer_size=300)
    dataset = dataset.repeat(self._num_epochs)
    dataset = dataset.batch(self._batch_size)
    data_iterator = dataset.make_one_shot_iterator()
    idx, features, labels = data_iterator.get_next()
    feature_infos = {}
    feature_infos['feature_idx'] = idx
    feature_infos['feature_values'] = features
    tf.logging.info(labels)
    return feature_infos, labels
 
 
  def train(self):
    """训练模型"""
    model = self.build_model()
    train_spec = tf.estimator.TrainSpec(input_fn=lambda: self.prepare_data_fn(data_mode='train'))
    val_spec = tf.estimator.EvalSpec(input_fn=lambda: self.prepare_data_fn(data_mode='val'))
    tf.estimator.train_and_evaluate(model, train_spec, val_spec)






点击以下标题查看更多往期内容: 





#投 稿 通 道#

 让你的论文被更多人看到 



如何才能让更多的优质内容以更短路径到达读者群体,缩短读者寻找优质内容的成本呢? 答案就是:你不认识的人。


总有一些你不认识的人,知道你想知道的东西。PaperWeekly 或许可以成为一座桥梁,促使不同背景、不同方向的学者和学术灵感相互碰撞,迸发出更多的可能性。 


PaperWeekly 鼓励高校实验室或个人,在我们的平台上分享各类优质内容,可以是最新论文解读,也可以是学习心得技术干货。我们的目的只有一个,让知识真正流动起来。


📝 来稿标准:

• 稿件确系个人原创作品,来稿需注明作者个人信息(姓名+学校/工作单位+学历/职位+研究方向) 

• 如果文章并非首发,请在投稿时提醒并附上所有已发布链接 

• PaperWeekly 默认每篇文章都是首发,均会添加“原创”标志


📬 投稿邮箱:

• 投稿邮箱:hr@paperweekly.site 

• 所有文章配图,请单独在附件中发送 

• 请留下即时联系方式(微信或手机),以便我们在编辑发布时和作者沟通




🔍


现在,在「知乎」也能找到我们了

进入知乎首页搜索「PaperWeekly」

点击「关注」订阅我们的专栏吧



关于PaperWeekly


PaperWeekly 是一个推荐、解读、讨论、报道人工智能前沿论文成果的学术平台。如果你研究或从事 AI 领域,欢迎在公众号后台点击「交流群」,小助手将把你带入 PaperWeekly 的交流群里。


▽ 点击 | 阅读原文 | 加入比赛

登录查看更多
37

相关内容

IEEE多媒体与博览会国际会议(ICME)每年有大约1,000名作者和500名参与者参加,这是由四个IEEE协会主办的联盟多媒体会议。它是一个促进交流多媒体最新进展的论坛从电路和系统,通信,计算机和信号处理社区的研究和开发角度来看的技术,系统和应用程序。 官网地址:http://dblp.uni-trier.de/db/conf/icmcs/
【快讯】KDD2020论文出炉,216篇上榜, 你的paper中了吗?
专知会员服务
50+阅读 · 2020年5月16日
斯坦福2020硬课《分布式算法与优化》
专知会员服务
117+阅读 · 2020年5月6日
新加坡南洋理工最新37页《零样本学习综述》论文
专知会员服务
109+阅读 · 2019年10月20日
计算机视觉最佳实践、代码示例和相关文档
专知会员服务
17+阅读 · 2019年10月9日
字节跳动 2019 ICME 双赛道冠军团队方案分享
PaperWeekly
50+阅读 · 2019年8月12日
【紫冬分享】自动化所团队获PRCV2018 美图短视频实时分类挑战赛冠军
中国科学院自动化研究所
10+阅读 · 2018年11月30日
Kaggle 新赛:第二届 YouTube-8M 视频理解挑战赛
AI研习社
10+阅读 · 2018年5月26日
应对时间序列问题有何妙招(Kaggle比赛亚军)
七月在线实验室
30+阅读 · 2018年3月19日
Arxiv
19+阅读 · 2019年11月23日
Arxiv
6+阅读 · 2019年4月4日
Arxiv
5+阅读 · 2018年5月1日
Arxiv
13+阅读 · 2018年4月18日
Arxiv
3+阅读 · 2012年11月20日
VIP会员
相关论文
Arxiv
19+阅读 · 2019年11月23日
Arxiv
6+阅读 · 2019年4月4日
Arxiv
5+阅读 · 2018年5月1日
Arxiv
13+阅读 · 2018年4月18日
Arxiv
3+阅读 · 2012年11月20日
Top
微信扫码咨询专知VIP会员