基于ZhiPuAI的文本匹配3(新闻推荐)

# 学习记录

        我们先网络上看到的内容都是,官方为我们精心挑选的。那么官方通过什么手段选择出来的内容捏,就是基于你所曾经浏览的内容。如果是新用户,那么在打开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)

        最关键就是在用户信息怎么选择,才可以返回用户感兴趣的。我们还可以将我们放回的信息进行排序,将用户会更大可能点击的放在前面。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值