用sklearn判断ins内容是否能上热门
背景
假设现在要使用爬虫从ins抓取内容,在ins的网页版上每个#标签下都有’热门’和’最新’两部分tab页,'热门’tab下只有9条内容,而’最新’tab页里页包含所有的热门内容,现在需要找到一个算法,将’最新’tab下的热门内容筛选出来。
那么现在我来介绍一下如何使用机器学习来实现这个算法,本文主要介绍从零开始使用机器学习并解决问题的过程,不会介绍细节。
开始之前要了解
- python:一种蛇
- instagram: 著名被墙网站之一
- pandas:数据处理类库
- matplotlib&seaborn: 画图类库
- 机器学习: 一种对计算机算法的研究方式,算法会根据经验自动优化效果
- 分类问题: 把一组数据分成两类或者多类,要划分类型已提前定义
- sklearn: 封装了多种机器学习算法的类库,开箱即用
数据处理
ins内容有很多字段信息,首先选择出可能影响内容上热门的字段,包含点赞/曝光/评论/发布时间/抓取时间/标题包含的tag数和当前页面tag下的内容总数等,这些内容用json格式保存,示例如下:
{
"id":"CAA-r0SjtF3",
"sourceTag":"dharmaproductions",
"publishTime":1589130910000,
"addTime":1589134125000,
"likes":4,
"comments":1,
"views":18,
"tagNumber":15,
"description":"",
"totalMedia":57149,
"hot":1
}
数据探索
这一步是为了进一步了解原始数据,检查数据真实性和字段的分布
- 用seaborn画直方图,查看热门/非热门内容的比例:
self.df = pd.read_json('debug/train_video.jl', lines=True)
sns.countplot(self.df['hot'], label="Count")
图中热门内容占比还是比较高的,有一点脱离真实情况,实际对于ins上被活跃使用的tag,本身内容数量就很多又更新频繁,所以只有很少一部分内容能上热门。
- 用seaborn画热力图,这一步是为了查看字段之间的关系:
self.df = pd.read_json('debug/train_video.jl', lines=True)
corr = self.df.corr()
plt.figure(figsize=(14, 14))
sns.heatmap(corr, annot=True)
corr()函数会计算数据集df中各字段的相关关系,图中的颜色越浅代表越相关,在左上角可以看到like/view之前相关性比较高,如果两个字段之间相关性接近1,可以考虑去掉其中一个字段。
- 用matplotlib画频率分布直方图,查看字段的分布类型
def histogram(self, items=None, index=None, field=None, y_label='Probability'):
"""
画频率直方图(带正态分布曲线)
:param index: 图片位置
:param field: 字段名
:param y_label:
:return:
"""
title = field + ' distribution'
if items is None:
items = self.df[field]
try:
plt.subplot(index)
mean = items.mean()
std = items.std()
x = np.arange(items.min(), items.max())
y = self.normfun(x=x, mu=mean, sigma=std)
plt.plot(x, y)
plt.hist(items, bins='auto', density=True, rwidth=0.9, stacked=True)
plt.title(title)
plt.xlabel(field)
plt.ylabel(y_label)
plt.tight_layout()
except Exception as e:
print(e)
图中蓝色的线是正态分布函数曲线,很明显like/view/comment的分布不符合正态分布,更像是长尾分布
数据清洗&特征选择
因为原始数据中并没有缺失值或异常值得情况,所以忽略数据清洗的步骤,直接进行特征选择.
首先我们不需要具体的时间戳,把发布时间publistTime和抓取时间addTime的间隔计算出来,单位是天和小时(ins热门tab中通常是最近发布的内容)
df['days'] = (pd.to_datetime(df['addTime'], unit='ms') - pd.to_datetime(df['publishTime'], unit='ms')).dt.days
# 不满一天的用1天替换
df['days'] = df['days'].replace(0, 1)
df['hours'] = ((pd.to_datetime(df['addTime'], unit='ms') - pd.to_datetime(df['publishTime'], unit='ms'))
.dt.total_seconds() / 3600).astype(int)
df['hours'] = df['hours'].replace(0, 1)
然后因为一般内容发布越早曝光也越高,所以添加like_per_hour/view_per_hour两个特征,减弱时间影响
df['like_per_hour'] = (df['likes'] / df['hours']).astype(int<