利用用户行为数据(1)——userCF

本文介绍了一个基于用户协同过滤的推荐系统实现案例。使用了MovieLens数据集,通过Python编程实现用户相似度计算,并据此推荐未观看过的电影。该文详细展示了如何通过分析用户行为数据来提升推荐系统的准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

跟着《推荐系统实践》用MovieLens数据集做了一下基于用户的协同过滤算法。

#coding: utf-8

import random
import math

K = 3
def SplitData(file, M, k, seed):
    test = dict()
    train = dict()
    random.seed(seed)
    with open(file, 'r') as rf:
        """
        f.read()\f.readline()\f.readlines()
        """
        for line in rf.readlines():
            dataTmp = line.split("::")
            """
            dataTmp[0]为user, 1为movie, 2为user对movie的打分
            """
            if random.randint(0,M) == k:
                if dataTmp[0] in test.keys():
                    test[dataTmp[0]][dataTmp[1]] = dataTmp[2]
                else:
                    test[dataTmp[0]] = dict()
                    test[dataTmp[0]][dataTmp[1]] = dataTmp[2]

            else:
                if dataTmp[0] in train.keys():
                    train[dataTmp[0]][dataTmp[1]] = dataTmp[2]
                else:
                    train[dataTmp[0]] = dict()
                    train[dataTmp[0]][dataTmp[1]] = dataTmp[2]

    return test, train

"""
生成用户倒排表
W存储用户u和用户v的相似度,key1:用户u,key2:用户v,value:相似度
"""
def UserSimilarity(train):
    item_users = dict()
	"""
    u是user, items是movie:rate
	item_users统计每部电影参与评分的用户。
	"""
    for u, items in train.items():
        for i in items.keys():
            if i not in item_users:
                item_users[i] = set()
            item_users[i].add(u)
    C = dict()
    N = dict()
	"""
	N记录每个用户评分电影的部数。
	C计算用户u和其他用户评同一部电影的次数。没有共同评分的电影,则不被记录。
	"""
    for i, users in item_users.items():
        for u in users:
            if u in N.keys():
                N[u] += 1
            else:
                N[u] = 1
            for v in users:
                if u == v:
                    continue
                if u in C.keys():
                    if v in C[u].keys():
                        C[u][v] += 1
                    else:
                        C[u][v] = 1
                else:
                    C[u] = dict()
                    C[u][v] = 1
					
    """
	W通过两个用户评分同一部电影的次数和这两个用户评分电影部数之积计算这两个用户的相似性。
	"""
    W = dict()
    for u, related_users in C.items():
        for v, cuv in related_users.items():
            if u == v:
                continue
            if u in W.keys():
                W[u][v] = cuv / math.sqrt(N[u] * N[v])
            else:
                W[u] = dict()
                W[u][v] = cuv / math.sqrt(N[u] * N[v])

    print(len(W))
    n = 0
    for u, related_users in W.items():
        print(u)
        print(related_users)
        n += 1
        if n > 10: break
    return W


"""
rvi为用户给电影的打分
通过相似用户对某部电影的打分来对电影进行排名。
"""
def Recommend(user, train, W):
    rank = dict()
    interacted_items = train[user]
    print(W[user])
    for v, wuv in sorted(W[user].items, key=W[user].items.values(), reverse = True)[0:K]:
        for i, rvi in train[v].items:
            if i in interacted_items:
                #filter items user interacted before
                continue
			if i in rank.keys():
				rank[i] += wuv * rvi
			else:
				rank[i] = dict()
				rank[i] = wuv * rvi
    print(rank)
    return rank


def main():
    data = []
    rate_file = "GroupLens_MovieLens/ml-1m/ml-1m/ratings.dat"
    test, train = SplitData(rate_file, 8, 4, 60)
    print(len(train))
    W = UserSimilarity(train)
    Recommend('59915', train, W)




if __name__ == '__main__':
    main()


### 用户画像标签的数据格式设计方案 用户画像标签的设计方案通常会依据不同的应用场景和技术栈来决定其存储方式和数据格式。以下是几种常见的用户画像标签数据格式设计及其特点。 #### Hive 存储中的数据格式 在基于 Hive 的存储方案中,用户画像标签可以通过 `map<string, string>` 类型的字段进行表示[^2]。这种设计能够灵活支持多维度的键值对形式的标签存储。具体表结构如下: ```sql CREATE TABLE dw.userprofile_userlabel_map_all ( userid STRING COMMENT '用户ID', userlabels MAP<STRING, STRING> COMMENT '标签映射' ) COMMENT '用户标签汇聚表' PARTITIONED BY (data_date STRING COMMENT '数据日期'); ``` 在此设计中: - **`userid`** 字段用于唯一标识某个用户。 - **`userlabels`** 是一个 Map 类型字段,其中 Key 表示标签名称,Value 则对应具体的标签值。例如,Key 可以为 `"gender"` 或 `"age_group"`,而 Value 则分别为 `"male"` 和 `"18-24"` 等[^2]。 这种方式的优点在于查询效率较高,适合批量处理场景下的数据分析需求。 #### HBase 存储中的数据格式 对于需要频繁更新或者实时访问的需求,HBase 提供了一种高效的解决方案。在这种情况下,每条记录由 RowKey(通常是 UserID)以及多个 Column Family 构成[^3]。一种典型的数据模型可能如下所示: | RowKey | cf:basic_info:gender | cf:behavioral_data:last_login_time | |--------|-----------------------|-------------------------------------| | u123 | male | 2023-10-01 | 上述表格展示了如何利用 HBase 来保存不同类型的用户属性信息。每一列代表特定的一组标签类别,如基本信息 (`cf:basic_info`) 或行为数据 (`cf:behavioral_data`)。这样做的好处是可以针对不同类型的数据设置独立的 TTL(Time To Live),从而优化资源利用率。 #### MySQL 存储中的数据格式 当涉及到较小规模的数据集或是需要复杂事务操作时,关系型数据库如 MySQL 成为了理想的选择之一。虽然它并不擅长大规模分布式计算,但在某些特殊场合下仍然非常有用——尤其是作为元数据管理工具或者是 ETL 过程的结果验证平台[^4]。 假设我们希望跟踪每日新增加了多少个新创建出来的标签,则可以在 MySQL 中建立一张简单的统计报表表单: ```sql CREATE TABLE etl_monitoring_stats( stat_date DATE NOT NULL, label_type VARCHAR(50), count INT DEFAULT 0, PRIMARY KEY(stat_date,label_type) ); ``` 该表允许管理员快速查看过去一段时间内的变化趋势,并据此调整后续的工作流程安排. --- ### 总结 综上所述,在实际项目实施过程中可以根据业务特性选择合适的存储介质及相应配套的数据格式定义策略。无论是采用 Hive 实现离线批处理还是借助于 HBase 达到准实时效果亦或是单纯依赖传统的关系型数据库完成辅助功能支撑,都需充分考虑性能指标、成本预算等因素后再做出最终决策。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值