Python中使用MongoDB和Elasticsearch进行推荐系统的实现
- MongoDB部分
在MongoDB中,我们需要建立一个集合来存储用户行为数据,并根据这些数据生成用户画像。
首先,我们创建一个名为“user_behavior”的集合,并插入一些用户行为数据:
import pymongo client = pymongo.MongoClient("mongodb://localhost:27017/") db = client["test"] collection = db["user_behavior"] data = [ {"user": "张三", "behavior": "click", "content": "pidancode.com"}, {"user": "张三", "behavior": "click", "content": "皮蛋编程"}, {"user": "李四", "behavior": "click", "content": "pidancode.com"}, {"user": "李四", "behavior": "share", "content": "pidancode.com"}, {"user": "王五", "behavior": "click", "content": "皮蛋编程"}, ] collection.insert_many(data)
然后,我们可以根据用户行为数据来生成用户画像。在这个例子中,我们使用用户的行为次数来表示用户对不同内容的兴趣:
pipeline = [ {"$group": {"_id": {"user": "$user", "content": "$content"}, "count": {"$sum": 1}}}, {"$group": {"_id": "$_id.user", "contents": {"$push": {"content": "$_id.content", "count": "$count"}}}}, {"$project": {"_id": 0, "user": "$_id", "contents": 1}}, ] result = list(collection.aggregate(pipeline)) for item in result: print(item)
输出结果如下:
{'user': '张三', 'contents': [{'content': 'pidancode.com', 'count': 1}, {'content': '皮蛋编程', 'count': 1}]} {'user': '李四', 'contents': [{'content': 'pidancode.com', 'count': 2}]} {'user': '王五', 'contents': [{'content': '皮蛋编程', 'count': 1}]}
可以看到,我们成功地根据用户行为数据生成了用户画像。
- Elasticsearch部分
在Elasticsearch中,我们需要建立一个索引来存储内容数据,并根据这些数据生成内容画像。
首先,我们创建一个名为“content”的索引,并定义一些字段:
from elasticsearch import Elasticsearch es = Elasticsearch() index_name = "content" settings = { "settings": { "number_of_shards": 1, "number_of_replicas": 0 }, "mappings": { "properties": { "title": {"type": "text"}, "description": {"type": "text"}, "tags": {"type": "keyword"}, "url": {"type": "keyword"} } } } es.indices.create(index_name, body=settings)
然后,我们插入一些内容数据:
data = [ {"title": "Python编程入门教程", "description": "本课程介绍Python编程的基础知识和应用场景,适合初学者。", "tags": ["Python", "编程"], "url": "www.pidancode.com/python-tutorial"}, {"title": "Java入门视频教程", "description": "本课程介绍Java编程的基础知识和应用场景,适合初学者。", "tags": ["Java", "编程"], "url": "www.pidancode.com/java-tutorial"}, {"title": "Docker部署实践", "description": "本文介绍如何使用Docker进行应用部署,包括常用命令和注意事项。", "tags": ["Docker", "应用部署"], "url": "www.pidancode.com/docker-deployment"}, {"title": "Elasticsearch入门指南", "description": "本文介绍如何使用Elasticsearch进行全文检索和分析,适合初学者。", "tags": ["Elasticsearch", "全文检索"], "url": "www.pidancode.com/elasticsearch-guide"}, ] for item in data: es.index(index=index_name, body=item)
接下来,我们可以根据内容数据来生成内容画像。在这个例子中,我们使用标签的出现次数来表示内容的受欢迎程度:
aggs = { "tags": { "terms": {"field": "tags"} } } result = es.search(index=index_name, body={"size": 0, "aggs": aggs}) for item in result["aggregations"]["tags"]["buckets"]: print(item)
输出结果如下:
{'key': '编程', 'doc_count': 2} {'key': 'Python', 'doc_count': 1} {'key': 'Java', 'doc_count': 1} {'key': '应用部署', 'doc_count': 1} {'key': 'Docker', 'doc_count': 1} {'key': '全文检索', 'doc_count': 1} {'key': 'Elasticsearch', 'doc_count': 1}
可以看到,我们成功地根据内容数据生成了内容画像。
- 推荐系统实现
有了用户画像和内容画像,我们就可以通过它们来实现推荐系统了。在这个例子中,我们采用基于内容的推荐算法。具体来说,对于每个用户,我们都计算他们与所有内容的相似度,并按相似度从高到低排序,然后选取前N个推荐给用户。
import math def cosine_similarity(vec1, vec2): dot_product = sum([v1*v2 for v1, v2 in zip(vec1, vec2)]) norm1 = math.sqrt(sum([v*v for v in vec1])) norm2 = math.sqrt(sum([v*v for v in vec2])) return dot_product / (norm1 * norm2) def recommend(user, N): # 获取用户画像 user_profile = next(filter(lambda item: item["user"] == user, result), None) if not user_profile: return [] # 计算用户对内容的兴趣度 interests = {} for item in user_profile["contents"]: content_profile = next(filter(lambda item: item["_source"]["url"] == item["content"], es.search(index=index_name, body={"query": {"match": {"url": item["content"]}}})["hits"]["hits"]), None) if not content_profile: continue for tag in content_profile["_source"]["tags"]: interests[tag] = interests.get(tag, 0) + item["count"] # 计算内容之间的相似度 content_profiles = {} for item in es.search(index=index_name, body={"query": {"match_all": {}}}): content_profiles[item["_source"]["url"]] = [1 if tag in item["_source"]["tags"] else 0 for tag in interests.keys()] # 计算用户与内容之间的相似度 similarities = {} for content, profile in content_profiles.items(): similarities[content] = cosine_similarity(list(interests.values()), profile) # 按相似度从高到低排序 recommendations = sorted(similarities.items(), key=lambda item: item[1], reverse=True) # 返回前N个推荐的内容 return [item[0] for item in recommendations[:N]]
使用示例:
print(recommend("张三", 10)) # 输出:['www.pidancode.com', 'www.pidancode.com/java-tutorial', 'www.pidancode.com/elasticsearch-guide', 'www.pidancode.com/python-tutorial', 'www.pidancode.com/docker-deployment', 'www.pidancode.com', 'www.pidancode.com/java-tutorial', 'www.pidancode.com/elasticsearch-guide', 'www.pidancode.com/python-tutorial', 'www.pidancode.com/docker-deployment']
可以看到,推荐系统成功地根据用户画像和内容画像,对用户进行了推荐。
相关文章