想到推荐算法,大家可能会想到电商和游戏。不过,随着短视频产品的崛起,推荐算法也迎来一个新的风口,被大量应用在短视频领域,吸引更多的用户看到自己喜欢的内容。
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。
在 TRACK 2 上,baseline 的结果分别为 like:86.5%,finish:69.8%。
Baseline 需要 TensorFlow 1.12.0。模型下载地址:
https://github.com/challenge-ICME2019-Bytedance/Bytedance_ICME_challenge
#——运行脚本——#
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 的交流群里。
▽ 点击 | 阅读原文 | 加入比赛