【Python使用】嘿马推荐系统全知识和项目开发教程第2篇:1.4 案例--基于协同过滤的电影推荐,1.5 推荐系统评估【附代码

教程总体简介:1.1 推荐系统简介 学习目标 1 推荐系统概念及产生背景 2 推荐系统的工作原理及作用 3 推荐系统和Web项目的区别 1.3 推荐算法 1 推荐模型构建流程 2 最经典的推荐算法:协同过滤推荐算法(Collaborative Filtering) 3 相似度计算(Similarity Calculation) 4 协同过滤推荐算法代码实现: 二 根据用户行为数据创建ALS模型并召回商品 2.0 用户行为数据拆分 2.1 预处理behavior_log数据集 2.2 根据用户对类目偏好打分训练ALS模型 三 CTR预估数据准备 3.1 分析并预处理raw_sample数据集 1.3 Hadoop优势 4.4 大数据产品与互联网产品结合 4.5 大数据应用--数据分析 4.6 数据分析案例 5.3 HBase 的安装与Shell操作 1 HBase的安装 2.3 HDFS设计思路 4.3 Hive 函数 1 内置运算符 2 内置函数 3 Hive 自定义函数和 Transform MapReduce实战 3.3.1 利用MRJob编写和运行MapReduce代码 3.3.2 运行MRJOB的不同方式 3.3.3 mrjob 实现 topN统计(实验) spark-core RDD常用算子练习 3.1 RDD 常用操作 3.2 RDD Transformation算子 3.4 Spark RDD两类算子执行示意 3、JSON数据的处理 3.1 介绍 3.2 实践 3.1 静态json数据的读取和操作 5.4 HappyBase操作Hbase 4.4 hive综合案例 四 LR实现CTR预估 4.1 Spark逻辑回归(LR)训练点击率预测模型 4、数据清洗 5.6 HBase组件 1、sparkStreaming概述 spark-core实战 5.1通过spark实现ip地址查询 五 离线推荐数据缓存 5.1离线数据缓存之离线召回集 1.4 案例--基于协同过滤的电影推荐 1 User-Based CF 预测电影评分 3 spark 安装部署及standalone模式介绍 1 spark 安装部署 3 spark 集群相关概念 六 实时产生推荐结果 6.1 推荐任务处理 推荐系统基础 Hadoop Hive HBase Spark SQL 1.6 推荐系统的冷启动问题 2 处理推荐系统冷启动问题的常用方法 一 个性化电商广告推荐系统介绍 1.2 项目效果展示 1.3 项目实现分析 1.4 点击率预测(CTR--Click-Through-Rate)概念 资源调度框架 YARN 3.1.1 什么是YARN 3.1.2 YARN产生背景 3.1.3 YARN的架构和执行流程 基于回归模型的协同过滤推荐 基于矩阵分解的CF算法 基于矩阵分解的CF算法实现(二):BiasSvd 基于内容的推荐算法(Content-Based) 基于内容的电影推荐:物品画像 基于TF-IDF的特征提取技术 基于内容的电影推荐:为用户产生TOP-N推荐结果 2、DataFrame 分布式处理框架 MapReduce 3.2.1 什么是MapReduce

完整笔记资料代码:https://gitee.com/yinuo112/Backend/tree/master/Python/嘿马推荐系统全知识和项目开发教程/note.md

感兴趣的小伙伴可以自取哦~


全套教程部分目录:


部分文件图片:

1.4 案例--基于协同过滤的电影推荐

学习目标

  • 应用基于用户的协同过滤实现电影评分预测
  • 应用基于物品的协同过滤实现电影评分预测

1 User-Based CF 预测电影评分

  • 数据集下载

  • 下载地址:[MovieLens Latest Datasets Small](

  • 建议下载[ml-latest-small.zip](

  • 加载ratings.csv,转换为用户-电影评分矩阵并计算用户之间相似度

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import osimport pandas as pd
import numpy as npDATA_PATH = "./datasets/ml-latest-small/ratings.csv"dtype = {"userId": np.int32, "movieId": np.int32, "rating": np.float32}# 加载数据,我们只用前三列数据,分别是用户ID,电影ID,已经用户对电影的对应评分ratings = pd.read_csv(data_path, dtype=dtype, usecols=range(3))# 透视表,将电影ID转换为列名称,转换成为一个User-Movie的评分矩阵ratings_matrix = ratings.pivot_table(index=["userId"], columns=["movieId"],values="rating")#计算用户之间相似度user_similar = ratings_matrix.T.corr()
  • 预测用户对物品的评分 (以用户1对电影1评分为例)

评分公式

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 1. 找出uid用户的相似用户similar_users = user_similar[1].drop([1]).dropna()# 相似用户筛选规则:正相关的用户similar_users = similar_users.where(similar_users>0).dropna()# 2. 从用户1的近邻相似用户中筛选出对物品1有评分记录的近邻用户ids = set(ratings_matrix[1].dropna().index)&set(similar_users.index)
finally_similar_users = similar_users.ix[list(1)]# 3. 结合uid用户与其近邻用户的相似度预测uid用户对iid物品的评分numerator = 0    # 评分预测公式的分子部分的值
denominator = 0    # 评分预测公式的分母部分的值
for sim_uid, similarity in finally_similar_users.iteritems():# 近邻用户的评分数据sim_user_rated_movies = ratings_matrix.ix[sim_uid].dropna()# 近邻用户对iid物品的评分sim_user_rating_for_item = sim_user_rated_movies[1]# 计算分子的值numerator += similarity * sim_user_rating_for_item# 计算分母的值denominator += similarity# 4 计算预测的评分值predict_rating = numerator/denominator
print("预测出用户<%d>对电影<%d>的评分:%0.2f" % (1, 1, predict_rating))
  • 封装成方法 预测任意用户对任意电影的评分
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def predict(uid, iid, ratings_matrix, user_similar):
    '''
    预测给定用户对给定物品的评分值
    :param uid: 用户ID
    :param iid: 物品ID
    :param ratings_matrix: 用户-物品评分矩阵
    :param user_similar: 用户两两相似度矩阵
    :return: 预测的评分值
    '''print("开始预测用户<%d>对电影<%d>的评分..."%(uid, iid))# 1. 找出uid用户的相似用户similar_users = user_similar[uid].drop([uid]).dropna()# 相似用户筛选规则:正相关的用户similar_users = similar_users.where(similar_users>0).dropna()if similar_users.empty is True:raise Exception("用户<%d>没有相似的用户" % uid)# 2. 从uid用户的近邻相似用户中筛选出对iid物品有评分记录的近邻用户ids = set(ratings_matrix[iid].dropna().index)&set(similar_users.index)finally_similar_users = similar_users.ix[list(ids)]# 3. 结合uid用户与其近邻用户的相似度预测uid用户对iid物品的评分numerator = 0    # 评分预测公式的分子部分的值denominator = 0    # 评分预测公式的分母部分的值for sim_uid, similarity in finally_similar_users.iteritems():# 近邻用户的评分数据sim_user_rated_movies = ratings_matrix.ix[sim_uid].dropna()# 近邻用户对iid物品的评分sim_user_rating_for_item = sim_user_rated_movies[iid]# 计算分子的值numerator += similarity * sim_user_rating_for_item# 计算分母的值denominator += similarity# 计算预测的评分值并返回predict_rating = numerator/denominatorprint("预测出用户<%d>对电影<%d>的评分:%0.2f" % (uid, iid, predict_rating))return round(predict_rating, 2)
  • 为某一用户预测所有电影评分
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def predict_all(uid, ratings_matrix, user_similar):
    '''
    预测全部评分
    :param uid: 用户id
    :param ratings_matrix: 用户-物品打分矩阵
    :param user_similar: 用户两两间的相似度
    :return: 生成器,逐个返回预测评分
    '''# 准备要预测的物品的id列表item_ids = ratings_matrix.columns# 逐个预测for iid in item_ids:try:rating = predict(uid, iid, ratings_matrix, user_similar)except Exception as e:print(e)else:yield uid, iid, rating
if __name__ == '__main__':for i in predict_all(1, ratings_matrix, user_similar):pass
  • 根据评分为指定用户推荐topN个电影
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def top_k_rs_result(k):results = predict_all(1, ratings_matrix, user_similar)return sorted(results, key=lambda x: x[2], reverse=True)[:k]
if __name__ == '__main__':from pprint import pprintresult = top_k_rs_result(20)pprint(result)

2 Item-Based CF 预测电影评分

  • 加载ratings.csv,转换为用户-电影评分矩阵并计算用户之间相似度
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import osimport pandas as pd
import numpy as npDATA_PATH = "./datasets/ml-latest-small/ratings.csv"dtype = {"userId": np.int32, "movieId": np.int32, "rating": np.float32}# 加载数据,我们只用前三列数据,分别是用户ID,电影ID,已经用户对电影的对应评分ratings = pd.read_csv(data_path, dtype=dtype, usecols=range(3))# 透视表,将电影ID转换为列名称,转换成为一个User-Movie的评分矩阵ratings_matrix = ratings.pivot_table(index=["userId"], columns=["movieId"],values="rating")#计算用户之间相似度item_similar = ratings_matrix.corr()
  • 预测用户对物品的评分 (以用户1对电影1评分为例)

评分公式

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 1. 找出iid物品的相似物品similar_items = item_similar[1].drop([1]).dropna()# 相似物品筛选规则:正相关的物品similar_items = similar_items.where(similar_items>0).dropna()# 2. 从iid物品的近邻相似物品中筛选出uid用户评分过的物品ids = set(ratings_matrix.ix[1].dropna().index)&set(similar_items.index)
finally_similar_items = similar_items.ix[list(ids)]# 3. 结合iid物品与其相似物品的相似度和uid用户对其相似物品的评分,预测uid对iid的评分numerator = 0    # 评分预测公式的分子部分的值
denominator = 0    # 评分预测公式的分母部分的值
for sim_iid, similarity in finally_similar_items.iteritems():# 近邻物品的评分数据sim_item_rated_movies = ratings_matrix[sim_iid].dropna()# 1用户对相似物品物品的评分sim_item_rating_from_user = sim_item_rated_movies[1]# 计算分子的值numerator += similarity * sim_item_rating_from_user# 计算分母的值denominator += similarity# 计算预测的评分值并返回predict_rating = sum_up/sum_down
print("预测出用户<%d>对电影<%d>的评分:%0.2f" % (uid, iid, predict_rating))
  • 封装成方法 预测任意用户对任意电影的评分
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def predict(uid, iid, ratings_matrix, user_similar):
    '''
    预测给定用户对给定物品的评分值
    :param uid: 用户ID
    :param iid: 物品ID
    :param ratings_matrix: 用户-物品评分矩阵
    :param user_similar: 用户两两相似度矩阵
    :return: 预测的评分值
    '''print("开始预测用户<%d>对电影<%d>的评分..."%(uid, iid))# 1. 找出uid用户的相似用户similar_users = user_similar[uid].drop([uid]).dropna()# 相似用户筛选规则:正相关的用户similar_users = similar_users.where(similar_users>0).dropna()if similar_users.empty is True:raise Exception("用户<%d>没有相似的用户" % uid)# 2. 从uid用户的近邻相似用户中筛选出对iid物品有评分记录的近邻用户ids = set(ratings_matrix[iid].dropna().index)&set(similar_users.index)finally_similar_users = similar_users.ix[list(ids)]# 3. 结合uid用户与其近邻用户的相似度预测uid用户对iid物品的评分numerator = 0    # 评分预测公式的分子部分的值denominator = 0    # 评分预测公式的分母部分的值for sim_uid, similarity in finally_similar_users.iteritems():# 近邻用户的评分数据sim_user_rated_movies = ratings_matrix.ix[sim_uid].dropna()# 近邻用户对iid物品的评分sim_user_rating_for_item = sim_user_rated_movies[iid]# 计算分子的值numerator += similarity * sim_user_rating_for_item# 计算分母的值denominator += similarity# 计算预测的评分值并返回predict_rating = numerator/denominatorprint("预测出用户<%d>对电影<%d>的评分:%0.2f" % (uid, iid, predict_rating))return round(predict_rating, 2)
  • 为某一用户预测所有电影评分
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def predict_all(uid, ratings_matrix, item_similar):
    '''
    预测全部评分
    :param uid: 用户id
    :param ratings_matrix: 用户-物品打分矩阵
    :param item_similar: 物品两两间的相似度
    :return: 生成器,逐个返回预测评分
    '''# 准备要预测的物品的id列表item_ids = ratings_matrix.columns# 逐个预测for iid in item_ids:try:rating = predict(uid, iid, ratings_matrix, item_similar)except Exception as e:print(e)else:yield uid, iid, ratingif __name__ == '__main__':for i in predict_all(1, ratings_matrix, item_similar):pass
  • 根据评分为指定用户推荐topN个电影
 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def top_k_rs_result(k):results = predict_all(1, ratings_matrix, item_similar)return sorted(results, key=lambda x: x[2], reverse=True)[:k]
if __name__ == '__main__':from pprint import pprintresult = top_k_rs_result(20)pprint(result)

3

1.5 推荐系统评估

学习目标

  • 了解推荐系统的常用评估指标
  • 了解推荐系统的评估方法

1 推荐系统的评估指标

  • 好的推荐系统可以实现用户, 服务提供方, 内容提供方的共赢

  • 评估数据来源显示反馈和隐式反馈
显式反馈隐式反馈
  • 常用评估指标

• 准确性 • 信任度 • 满意度 • 实时性 • 覆盖率 • 鲁棒性 • 多样性 • 可扩展性 • 新颖性 • 商业⽬标 • 惊喜度 • ⽤户留存

  • 准确性 (理论角度) Netflix 美国录像带租赁

    • 评分预测

      • RMSE MAE
    • topN推荐

      • 召回率 精准率
  • 准确性 (业务角度)

  • 覆盖度

    • 信息熵 对于推荐越大越好
    • 覆盖率
  • 多样性&新颖性&惊喜性

    • 多样性:推荐列表中两两物品的不相似性。(相似性如何度量?
    • 新颖性:未曾关注的类别、作者;推荐结果的平均流⾏度
    • 惊喜性:历史不相似(惊)但很满意(喜)
    • 往往需要牺牲准确性
    • 使⽤历史⾏为预测⽤户对某个物品的喜爱程度
    • 系统过度强调实时性
  • Exploitation & Exploration 探索与利用问题

    • Exploitation(开发 利用):选择现在可能最佳的⽅案
    • Exploration(探测 搜索):选择现在不确定的⼀些⽅案,但未来可能会有⾼收益的⽅案
    • 在做两类决策的过程中,不断更新对所有决策的不确定性的认知,优化 长期的⽬标
  • EE问题实践

    • 兴趣扩展: 相似话题, 搭配推荐
    • 人群算法: userCF 用户聚类
    • 平衡个性化推荐和热门推荐比例
    • 随机丢弃用户行为历史
    • 随机扰动模型参数
  • EE可能带来的问题

    • 探索伤害用户体验, 可能导致用户流失
    • 探索带来的长期收益(留存率)评估周期长, KPI压力大
    • 如何平衡实时兴趣和长期兴趣
    • 如何平衡短期产品体验和长期系统生态
    • 如何平衡大众口味和小众需求

2 推荐系统评估方法

  • 评估方法

  • 问卷调查: 成本高

  • 离线评估:

    • 只能在用户看到过的候选集上做评估, 且跟线上真实效果存在偏差
    • 只能评估少数指标
    • 速度快, 不损害用户体验
  • 在线评估: 灰度发布 & A/B测试 50% 全量上线

  • 实践: 离线评估和在线评估结合, 定期做问卷调查

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/74526.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

运算放大器(五)电压比较器

比较器在最常用的简单集成电路中排名第二&#xff0c;仅次于排名第一的运算放大器。 电压比较器是一种用来比较输入信号电压与参考电压大小&#xff0c;并将比较结果以高电平或低电平形式输出的一种信号处理电路&#xff0c;广泛应用于各种非正弦波的产生和变换电路中&#xf…

Java面试黄金宝典34

1. 主键索引底层的实现原理 定义 主键索引是数据库中用于唯一标识表中每一行记录的索引&#xff0c;常见的底层实现是 B 树结构。B 树是一种平衡的多路搜索树&#xff0c;由内部节点和叶子节点组成。内部节点只存储索引键和指向下一层节点的指针&#xff0c;不存储实际数据&am…

Educational Codeforces Round 177 (Rated for Div. 2)

Educational Codeforces Round 177 (Rated for Div. 2) A. Cloudberry Jam 思路&#xff1a; 1千克果子能生产2/3千克果酱&#xff0c;生产3千克果酱则需要2千克果酱&#xff0c;所以*2即可 code: void solve() { int x; cin >> x;cout << 2 * x << e…

ARM-外部中断,ADC模数转换器

根据您提供的图片&#xff0c;我们可以看到一个S3C2440微控制器的中断处理流程图。这个流程图展示了从中断请求源到CPU的整个中断处理过程。以下是流程图中各个部分与您提供的寄存器之间的关系&#xff1a; 请求源&#xff08;带sub寄存器&#xff09;&#xff1a; 这些是具体的…

23种设计模式-行为型模式-迭代器

文章目录 简介问题解决代码设计关键点&#xff1a; 总结 简介 迭代器是一种行为设计模式&#xff0c;让你能在不暴露集合底层表现形式(列表、栈和树等)的情况下遍历集合中所有的元素。 问题 集合是编程中最常使用的数据类型之一。 大部分集合使用简单列表存储元素。但有些集…

Python 布尔类型

Python 布尔类型(Boolean) 布尔类型是Python中的基本数据类型之一&#xff0c;用于表示逻辑值。它只有两个值&#xff1a; True - 表示真False - 表示假 1. 布尔值的基本使用 # 定义布尔变量 is_active True is_admin Falseprint(is_active) # 输出: True print(is_admi…

人工智能在前端开发中的应用探索

一、人工智能在前端开发中的应用场景 人工智能&#xff08;AI&#xff09;技术的快速发展为前端开发带来了新的机遇和挑战。AI在前端开发中的应用主要集中在以下几个方面&#xff1a;智能代码生成、自动化测试、个性化推荐、智能交互设计以及性能优化。这些应用场景不仅提高了…

三维扫描助力文化遗产数字化保护

当下&#xff0c;三维扫描技术以其独特的优势&#xff0c;正逐渐成为文化遗产数字化保护的重要工具&#xff0c;让珍贵的文物得以“永生”。 三维扫描在文物数字化方面的应用&#xff1a; 高精度文物存档&#xff1a;三维扫描技术能够实现对文物的快速、无损扫描&#xff0c;…

如何将生活场景转换为数据模型模型仿真?

从家到公司有31公里&#xff0c;其中有一个2车道右转立交桥汇入另外一条路&#xff0c;每次都是那个堵车&#xff0c;导致路上的行程在45分钟到70分钟左右&#xff1f;前面或后面路段都是3-4车道&#xff0c;足够通行。如何解决这个难题&#xff0c;是否可搭建数学模型实现可视…

Java学习总结-io流-练习案例

将文档的内容排序&#xff1a; public static void main(String[] args) throws IOException {File dir new File("J:\\360downloads\\wpcache\\srvsetwp\\xxx\\test.txt");BufferedReader br new BufferedReader(new FileReader(dir));//把按行读取到的内容&#…

【C++】STL库_stack_queue 的模拟实现

栈&#xff08;Stack&#xff09;、队列&#xff08;Queue&#xff09;是C STL中的经典容器适配器 容器适配器特性 不是独立容器&#xff0c;依赖底层容器&#xff08;deque/vector/list&#xff09;通过限制基础容器接口实现特定访问模式不支持迭代器操作&#xff08;无法遍历…

LangChain核心解析:掌握AI开发的“链“式思维

0. 思维导图 1. 引言 🌟 在人工智能快速发展的今天,如何有效地利用大语言模型(LLM)构建强大的应用成为众多开发者关注的焦点。前面的课程中,我们学习了正则表达式以及向量数据库的相关知识,了解了如何处理文档并将其附加给大模型。本章我们将深入探讨LangChain中的核心概…

Error:java: 程序包lombok不存在

使用Maven package打包项目发现报错 一、Maven配置文件修改 1.找到本地 maven的配置文件settings.xml 2.修改配置文件中&#xff0c;指向本地仓库的地址使用 ‘’ \ \ ‘’ 隔开&#xff0c; 要么使用 正斜线 / 隔开 不要使用 反斜线 \ windows OS 电脑&#xff0c;使用 \ …

WordPress 未授权本地文件包含漏洞(CVE-2025-2294)(附脚本)

免责申明: 本文所描述的漏洞及其复现步骤仅供网络安全研究与教育目的使用。任何人不得将本文提供的信息用于非法目的或未经授权的系统测试。作者不对任何由于使用本文信息而导致的直接或间接损害承担责任。如涉及侵权,请及时与我们联系,我们将尽快处理并删除相关内容。 0x0…

基于 C# 开发视觉检测系统项目全解析

引言 在当今高度自动化的制造业领域,视觉检测系统的重要性愈发凸显。它凭借高速、高精度的特性,在产品外观缺陷检测、尺寸测量等环节发挥着关键作用,显著提升了生产效率和产品质量。C# 作为一种功能强大且易于学习的编程语言,结合.NET 框架丰富的类库以及 Windows Forms、…

GISBox:核心功能免费的一站式三维GIS处理平台

大家好&#xff0c;今天为大家介绍的软件是GISBox&#xff1a;一款核心功能免费的一站式三维GIS处理平台&#xff0c;主要是适用于数字孪生。下面&#xff0c;我们将从软件的主要功能、支持的系统、软件官网等方面对其进行简单的介绍。 软件官网&#xff1a;http://www.gisbox.…

Ubuntu 24 云服务器上部署网站_详细版_1

从零开始&#xff0c;在 Ubuntu 24 云服务器上部署一个支持登录和权限的网站&#xff0c;用 Python Django 实现&#xff0c;适合新手跟着操作。 &#x1f527; 第一步&#xff1a;更新服务器并安装基础环境 请使用 SSH 登录你的 Ubuntu 24 云服务器&#xff08;用 MobaXterm…

单片机学习之定时器

定时器是用来定时的机器&#xff0c;是存在于STM32单片机中的一个外设。STM32一般总共有8个定时器&#xff0c;分别是2个高级定时器&#xff08;TIM1、TIM8&#xff09;&#xff0c;4个通用定时器&#xff08;TIM2、TIM3、TIM4、TIM5&#xff09;和2个基本定时器&#xff08;TI…

AIGC6——AI的哲学困境:主体性、认知边界与“天人智一“的再思考

引言&#xff1a;当机器开始"思考" 2023年&#xff0c;Google工程师Blake Lemoine声称对话AI LaMDA具有"自我意识"&#xff0c;引发轩然大波。这一事件将古老的哲学问题重新抛回公众视野&#xff1a;​**机器能否拥有主体性&#xff1f;**从东方"天人…

从内核到应用层:Linux缓冲机制与语言缓冲区的协同解析

系列文章目录 文章目录 系列文章目录前言一、缓冲区1.1 示例11.2 缓冲区的概念 二、缓冲区刷新方案三、缓冲区的作用及存储 前言 上篇我们介绍了&#xff0c;文件的重定向操作以及文件描述符的概念&#xff0c;今天我们再来学习一个和文件相关的知识-----------用户缓冲区。 在…