推荐系统

引入

​ 在几乎所有购物平台(如京东,淘宝)或其他平台都会有一个推荐模块,然后网站里的搜索框里面点击的时候都会带有一个默认的关键词,这就是嵌入了推荐系统的智能化的平台。

电商(无推荐系统)

  • 缺点:所有数据纯粹的增删改查,无法个性化的对用户推送物品

用户查找自己可能想要的商品 --> 解决方案:

  • 搜索栏搜索
  • 查看用户分类

这种方法可行,但这种应适用于已有明确要购买的商品时。有时候可能只是想看看有什么想买的物品但没有明确的目标时这种方法就不适用。

电商(有推荐系统)

意义

​ 传统的数据库查询无法有效的向用户推送用户想要的商品,从而使购物平台的使用感受不好,通过推荐算法可以根据用户的历史行为,购物偏好,个性化的向用户推荐商品。

应用

  1. 展示页(利用推荐系统生成用户意向度最高的几个物品)
  2. 搜索功能(默认会有个用户当前意向度最高的物品)

功能原理

​ 通过整合用户的行为(点击,收藏,评分,评论,过去购物等)进行分权排序,然后再进行推荐,这样就可以让推荐的商品尽可能的符合用户的需求

技术原理(基于机器学习,前置知识numpy,pandas)

TF-IDF

  • 通过结合TF算法和IDF算法,文本的关键词检索
TF
  • 表示词条(关键字)在文本中出现的频率
IDF
  • 表示逆向词频率,总文件数目除以包含该词语的文件的数目

代码演示

import pandas as pd
import numpy as np

docA = "The cat like eat fish"
docB = "The dog like eat meat"

bowA = docA.split(" ")
bowB = docB.split(" ")

# 构建完整词库
wordSet = set(bowA).union(set(bowB))
print("完整词库:")
print(wordSet)

# 进行词数统计
# 用统计字典保存出现的次数

wordDictA = dict.fromkeys(wordSet, 0)
wordDictB = dict.fromkeys(wordSet, 0)

# 遍历文档统计次数
for word in bowA:
    wordDictA[word] += 1

for word in bowB:
    wordDictB[word] += 1

print("统计结果:")
print(pd.DataFrame([wordDictA, wordDictB]))


# 计算词频
def computeTF(wordDict, bow):

    # 用一个字典对象记录tf,把所有的词对应在bow文档里的tf都算出来
    tfDict = {}
    nbowCount = len(bow)

    for word, count in wordDict.items():
        tfDict[word] = count / nbowCount
    return tfDict

tfA = computeTF(wordDictA, bowA)
tfB = computeTF(wordDictB, bowB)


# 计算逆文档频率
def computeIDF(wordDictList):
    # 用一个字典对象保存IDF结果,每一个词作为key
    idfDict = dict.fromkeys(wordDictList[0], 0)
    N = len(wordDictList)
    import math

    for wordDict in wordDictList:
        # 遍历字典中的每个词汇
        for word, count in wordDict.items():
            if count > 0:
                idfDict[word] += 1

    # 已经得到所有词汇i对应的Ni, 现在根据公式把它替换成idf
    for word, ni in idfDict.items():
        idfDict[word] = math.log10((N + 1) / (ni + 1))
    return idfDict


idfs = computeIDF( [wordDictA, wordDictB])


# 计算TF-IDF
def computeTFIDF(tf, idfs):
    tfidf = {}
    for word, tfval in tf.items():
        tfidf[word] = tfval * idfs[word]
    return tfidf


tfidfA = computeTFIDF(tfA, idfs)
tfidfB = computeTFIDF(tfB, idfs)
print(pd.DataFrame([tfidfA, tfidfB]))

运行结果

完整词库:
{'fish', 'eat', 'The', 'dog', 'cat', 'like', 'meat'}
统计结果:
   fish  eat  The  dog  cat  like  meat
0     1    1    1    0    1     1     0
1     0    1    1    1    0     1     1
       fish  eat  The       dog       cat  like      meat
0  0.035218  0.0  0.0  0.000000  0.035218   0.0  0.000000
1  0.000000  0.0  0.0  0.035218  0.000000   0.0  0.035218

协同过滤

基于用户的协同过滤
  • 通过用户的相似度矩阵进行推荐

  • 步骤

    1. 数据处理
    2. 计算用户相似度矩阵(粗排)
    3. 根据用户相似度矩阵对商品进行分权排序(精排)
实现步骤
  • 数据层

    ​ 1、数据获取(csv、数据库等)

    import pandas as pd
    pd.read_csv(data_path) # read_csv是pandas里面加载csv文件的函数, data_path为数据源路径
    

    ​ 2、数据处理(调整数据格式、查重、特征编码、归一化等)

    # 调整数据格式
    data = data.pivot_table(values='values_demo', index='index_demo', columns='columns_demo')
    # value_demo是值
    # index_demo是索引值
    # colums_demo是列名
    
  • 粗排(用户排序)

    ​ 1、根据相似度算法生成用户相似度矩阵

    cosine_similarity(data.fillna(0)) # 余弦相似度、fillna(0)表示将data里面的空值赋0值
    

    ​ 2、对相似度矩阵进行排序得到用户粗排序

    sorted(user_similarity[user].items(), key= lambda x: -x[1])
    # sorted是python内置的排序函数, 根据用户相似度矩阵进行排序,lambda x: -x[1]表示排根据第二个索引的值排倒序
    
  • 精排(物品排序)

    根据用户行为的权重结合用户相似度排序进行最终物品排序

​ 精排部分通常根据具体需求和行为的权重进行程序开发

完整代码

import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity


# 加载数据
def load_data(data_path):
    data = pd.read_csv(data_path)
    print("原始数据:")
    print(data)

    # 整理数据
    data = data.pivot_table(values='score', index='user_id', columns='movie_id')
    return data

# 构造相似度矩阵
def get_similarityMatrix(data):
    user_similarity = pd.DataFrame(
        cosine_similarity(data.fillna(0)),
        index=data.index, columns=data.index
    )
    print(user_similarity)
    return user_similarity

# userCF
def user_cf(data, user_similarity):
    # print(data)
    print(user_similarity)


    result = {}
    for user, movie_list in data.iterrows():
        # 获取该用户看过的电影
        watched = []
        scores = {}
        for movie_name,movie_score in movie_list.items():
            if pd.isnull(movie_score) == False:
                watched.append(movie_name)

        # 获取相似度前5的用户
        for otheruser, score in sorted(user_similarity[user].items(), key= lambda x: -x[1])[:5]:
            if otheruser != user:
                # 获取前5相似的用户看过的电影
                for movie_name, movie_score in data.loc[otheruser].items():
                    if pd.isnull(movie_score) == False and movie_name not in watched:
                        scores[movie_name] = scores.get(movie_score, 0) + (score * movie_score)


        print(scores)
        for movie_name, movie_score in sorted(scores.items(), key = lambda x: -x[1])[:5]:
            result.setdefault(user, []).append(movie_name)
        print("=====================")


    return result



if __name__ == '__main__':

    data_path = "data/ml-1m/data_with_rating.csv"

    # 加载数据
    data = load_data(data_path)

    # 构造相似度矩阵
    user_similarity = get_similarityMatrix(data)

    # 核心算法(基于用户的协同过滤)
    result = user_cf(data, user_similarity)

    result = pd.DataFrame({
        'user_id': result.keys(),
        'movie_id': result.values()
    })
    print(result)
基于物品的协同过滤

和基于用户的协同过滤相似,需要计算物品相似度

基于深度学习的推荐算法
生成式推荐算法

拓展

美团推荐系统(https://tech.meituan.com/2015/01/22/mt-recommend-practice.html)

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐