# 学习记录
我们先网络上看到的内容都是,官方为我们精心挑选的。那么官方通过什么手段选择出来的内容捏,就是基于你所曾经浏览的内容。如果是新用户,那么在打开app的时候官方大多数都会让你选择你感兴趣的频道,那么这些就会曾为你的标签,那么官方向你发送时就会加大这部分的权重。
我们以新闻为例,我们将标题和导语作为匹配的文本(实践现实中会根据复杂),与你曾经浏览的文章作为对比相似度,与你浏览文章相似度高的新闻就会推送给你。另外还有一种就是所有用户都浏览的新闻,即高热度新闻也会被推荐到主页。
知道基本原理我们先导入zhipuai,以及api_key,前面两节都有提及这里就省略写了。
from zhipuai import ZhipuAI
zhipu = ZhipuAI(api_key="you_key")
def get_embedding(text):
emb_req = zhipu.embeddings.create(
model='embedding-2',
input=text
)
return emb_req.data[0].embedding
我们导入的数据集:AG News Classification Dataset | Kaggle
百度网盘链接: https://pan.baidu.com/s/1oLZdBrI6Us-nxjZIotRm4Q?pwd=kkjj 提取码: kkjj
import pandas as pd
# 填文件的地址
df = pd.read_csv("C:\\Users\\User\\Desktop\\机器算法and data\\Embedding\\train.csv")
# 查看一下大小和每一个维度的含有
print(df.shape, '\n', df.columns)
我们可以发现数据有一点多(120000,3),那么我们看看每一个种类有多少种
# 查看每一个种类有多少
cf = df['Class Index'].value_counts()
print(cf)
发现有四个种类,每一个种类有30000个,那么我们随机采样200个数据,数据太多负担不起。顺便看看数据长什么样。
sdf = df.sample(200, random_state=42)
print(sdf['Class Index'].value_counts())
# sdf.iloc[1]是按位置取值,与numpy的索引类似
print(sdf.iloc[1])
将所有的200条数据embedding化,需要embedding的是标题和描述。导入numpy包和sklearn计算相似度的包
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
sdf['embedding'] = sdf.apply(lambda x:get_embedding(x.Title+x.Description), axis=1)
我们建立一个用户的喜好和浏览记录,@dataclass,需要python3.7+版本以上使用
from dataclasses import dataclass
from typing import List
@dataclass
class User:
user_name: str
@dataclass
class UserPrefer:
user_name: str
prefers: List[int]
@dataclass
class Item:
item_id: str
item_props: dict
@dataclass
class Action:
action_type: str
action_props: dict
@dataclass
class UserAction:
user: User
item: Item
action: Action
action_time: str
# 创建用户
u1 = User("u1")
up1 = UserPrefer("u1", [1, 2])
# sdf.iloc[1] 正好是sport(类别为2)
i1 = Item("i1", {
"id": 1,
"catetory": "sport",
"title": "Swimming: Shibata Joins Japanese Gold Rush",
"description": "\
ATHENS (Reuters) - Ai Shibata wore down French teen-ager Laure Manaudou to win the women's 800 meters \
freestyle gold medal at the Athens Olympics Friday and provide Japan with their first female swimming \
champion in 12 years.",
"content": "content"
})
a1 = Action("浏览", {
"open_time": "2023-04-01 12:00:00",
"leave_time": "2023-04-01 14:00:00",
"type": "close",
"duration": "2hour"
})
# 别对应的是UserAction中的user, item, action, action_time
ua1 = UserAction(u1, i1, a1, "2023-04-01 12:00:00")
接下来就是要将用户的行为去与新闻库中的新闻进行匹配,即是召回。
class Recall:
def __init__(self, df: pd.DataFrame):
self.data = df
def user_prefer_recall(self, user, n):
up = self.get_user_prefers(user)
idx = random.randrange(0, len(up.prefers))
return self.pick_by_idx(idx, n)
def hot_recall(self, n):
# 随机进行示例
df = self.data.sample(n)
return df
def user_action_recall(self, user, n):
# 返回的参数是ua1,就是UserAction,里面的内容是user, item, action, action_time
actions = self.get_user_actions(user)
# 获取用户浏览的过的那条新闻
interest = self.get_most_interested_item(actions)
recoms = self.recommend_by_interest(interest, n)
return recoms
def get_most_interested_item(self, user_action):
"""
可以选近一段时间内用户交互时间、次数、评论(相关属性)过的Item
"""
# 这里根据传入的参数UserAction,里面的内容是user, item, action, action_time
# 选择的是item中的item_props中的id
idx = user_action.item.item_props["id"]
# 根据id获取新闻
im = self.data.iloc[idx]
return im
def recommend_by_interest(self, interest, n):
# 确定用户浏览类别的大类
cate_id = interest["Class Index"]
# 获取用户浏览的新闻的embedding
q_emb = interest["embedding"]
# 选取这个大类中的新闻
base = self.data[self.data["Class Index"] == cate_id]
# 此处可以复用QA那一段代码,用给定embedding计算base中embedding的相似度
base_arr = np.array(
[v.embedding for v in base.itertuples()]
)
q_arr = np.expand_dims(q_emb, 0)
sims = cosine_similarity(base_arr, q_arr)
# 排除掉自己,取最相似的n个,最相似的是肯定是自己,所有是0就不能取,所以取后n个
idxes = sims.argsort(0).squeeze()[-(n + 1):-1]
return base.iloc[reversed(idxes.tolist())]
def pick_by_idx(self, category, n):
df = self.data[self.data["Class Index"] == category]
return df.sample(n)
def get_user_actions(self, user):
dct = {"u1": ua1}
return dct[user.user_name]
def get_user_prefers(self, user):
dct = {"u1": up1}
return dct[user.user_name]
def run(self, user):
ur = self.user_action_recall(user, 5)
# 如果用户没有交互过,则使用用户偏好召回
if len(ur) == 0:
ur = self.user_prefer_recall(user, 5)
hr = self.hot_recall(3)
# 将用户行为推荐和热门合并
return pd.concat([ur, hr], axis=0)
得到推荐的内容,我们只需要将data传进class里面,然后选取用户就可以得到,这个用户会获得的推荐新闻
re = Recall(sdf)
user_r = r.run(u1)
print(user_r)
最关键就是在用户信息怎么选择,才可以返回用户感兴趣的。我们还可以将我们放回的信息进行排序,将用户会更大可能点击的放在前面。