基于内容的推荐算法的实现代码实例

本次实例需要三个数据文件

分别为节目及其所属标签类型的01矩阵;用户--节目评分矩阵;用户收视了的节目--标签01矩阵。

可以直接下载下来使用https://download.csdn.net/download/qq_38281438/10757266

具体代码如下:

# -*- coding: utf-8 -*-
"""
Created on Thu Nov  1 09:33:14 2018

@author: AZ
"""
import math
import pandas as pd
import numpy as np
import os
os.chdir('E:/广电大数据营销推荐项目案例/数据清洗/电视节目信息数据预处理')

# 创建节目画像
# 参数说明:
# items_profiles = {item1:{'label1':1, 'label2': 0, 'label3': 0, ...}, item2:{...}...}
def createItemsProfiles(data_array, labels_names, items_names):
    items_profiles = {}
    for i in range(len(items_names)):
        items_profiles[items_names[i]] = {}
        for j in range(len(labels_names)):
            items_profiles[items_names[i]][labels_names[j]] = data_array[i][j]
    return items_profiles

# 创建用户画像
# 参数说明:
# data_array: 所有用户对于其所看过的节目的评分矩阵 data_array = [[2, 0, 0, 1.1, ...], [0, 0, 1.1, ...], ...]
# users_profiles = {user1:{'label1':1.1, 'label2': 0.5, 'label3': 0.0, ...}, user2:{...}...}
def createUsersProfiles(data_array, users_names, items_names, labels_names, items_profiles):
    users_profiles = {}
    # 计算每个用户对所看过的所有节目的平均隐性评分
    # users_average_scores_list = [1.2, 2.2, 4.3,...]
    users_average_scores_list = []

    # 统计每个用户所看过的节目(不加入隐性评分信息)
    # items_users_saw = {user1:[item1, item3, item5], user2:[...],...}
    items_users_saw = {}
    # 统计每个用户所看过的节目及评分
    # items_users_saw_scores = {user1:[[item1, 1.1], [item2, 4.1]], user2:...}
    items_users_saw_scores = {}
    
    for i in range(len(users_names)):

        items_users_saw_scores[users_names[i]] = []
        items_users_saw[users_names[i]] = []
        count = 0
        sum = 0.0
        for j in range(len(items_names)):

            # 用户对该节目隐性评分为正,表示真正看过该节目
            if data_array[i][j] > 0:
                items_users_saw[users_names[i]].append(items_names[j])
                items_users_saw_scores[users_names[i]].append([items_names[j], data_array[i][j]])
                count += 1
                sum += data_array[i][j]

        if count == 0:
            users_average_scores_list.append(0)
        else:
            users_average_scores_list.append(sum / count)

    for i in range(len(users_names)):

        users_profiles[users_names[i]] = {}

        for j in range(len(labels_names)):
            count = 0
            score = 0.0

            for item in items_users_saw_scores[users_names[i]]:

                # 参数:
                # 用户user1对于类型label1的隐性评分: user1_score_to_label1
                # 用户user1对于其看过的含有类型label1的节目item i 的评分: score_to_item i
                # 用户user1对其所看过的所有节目的平均评分: user1_average_score
                # 用户user1看过的节目总数: items_count

                # 公式: user1_score_to_label1 = Sigma(score_to_item i - user1_average_score)/items_count

                # 该节目含有特定标签labels_names[j]
                if items_profiles[item[0]][labels_names[j]] > 0:
                    score += (item[1] - users_average_scores_list[i])
                    count += 1

            # 如果求出的值太小,直接置0
            if abs(score) < 1e-6:
                score = 0.0
            if count == 0:
                result = 0.0
            else:
                result = score / count
            users_profiles[users_names[i]][labels_names[j]] = result
    return (users_profiles, items_users_saw)

# 创建节目画像
# 参数说明:
# items_profiles = {item1:{'label1':1, 'label2': 0, 'label3': 0, ...}, item2:{...}...}
def createItemsProfiles(data_array, labels_names, items_names):

    items_profiles = {}

    for i in range(len(items_names)):

        items_profiles[items_names[i]] = {}

        for j in range(len(labels_names)):
            items_profiles[items_names[i]][labels_names[j]] = data_array[i][j]

    return items_profiles

# 计算用户画像向量与节目画像向量的距离(相似度)
# 向量相似度计算公式:
# cos(user, item) = sigma_ui/sqrt(sigma_u * sigma_i)

# 参数说明:
# user_profile: 某一用户user的画像 user = {'label1':1.1, 'label2': 0.5, 'label3': 0.0, ...}
# item: 某一节目item的画像 item = {'label1':1, 'label2': 0, 'label3': 0, ...}
# labels_names: 所有类型名
def calCosDistance(user, item, labels_names):

    sigma_ui = 0.0
    sigma_u = 0.0
    sigma_i = 0.0

    for label in labels_names:
        sigma_ui += user[label] * item[label]
        sigma_u += (user[label] * user[label])
        sigma_i += (item[label] * item[label])

    if sigma_u == 0.0 or sigma_i == 0.0:  # 若分母为0,相似度为0
        return 0

    return sigma_ui/math.sqrt(sigma_u * sigma_i)


# 基于内容的推荐算法:
# 借助特定某个用户user的画像user_profile和备选推荐节目集的画像items_profiles,通过计算向量之间的相似度得出推荐节目集

# 参数说明:
# user_profile: 某一用户user的画像 user_profile = {'label1':1.1, 'label2': 0.5, 'label3': 0.0, ...}
# items_profiles: 备选推荐节目集的节目画像: items_profiles = {item1:{'label1':1, 'label2': 0, 'label3': 0}, item2:{...}...}
# items_names: 备选推荐节目集中的所有节目名
# labels_names: 所有类型名
# items_user_saw: 用户user看过的节目

def contentBased(user_profile, items_profiles, items_names, labels_names, items_user_saw):
    # 对于用户user的推荐节目集为 recommend_items = [[节目名, 该节目画像与该用户画像的相似度], ...]
    recommend_items = []

    for i in range(len(items_names)):
        # 从备选推荐节目集中的选择用户user没有看过的节目
        if items_names[i] not in items_user_saw:
            recommend_items.append([items_names[i], calCosDistance(user_profile, items_profiles[items_names[i]], labels_names)])
    # 将推荐节目集按相似度降序排列
    recommend_items.sort(key=lambda item: item[1], reverse=True)

    return recommend_items

# 输出推荐给该用户的节目列表
# max_num:最多输出的推荐节目数
def printRecommendedItems(recommend_items_sorted, max_num):
    count = 0
    for item, degree in recommend_items_sorted:
        print("节目名:%s, 推荐指数:%f" % (item, degree))
        count += 1
        if count == max_num:
            break

#主程序
if __name__ == '__main__':
    all_users_names = ['3','13','23']
    #按指定顺序排列所有的标签
    all_labels = ['剧情', '西部', '家庭', '惊悚', '动画', 
            '爱情', '情色', '运动', '音乐', '灾难', 
            '悬疑', '儿童', '短片', '历史', '动作', 
            '科幻', '传记', '同性', '冒险', '歌舞',
            '脱口秀', '真人秀', '新闻', '恐怖', '奇幻',
            '犯罪', '喜剧', '纪录片', '战争', '古装', 
            '武侠', '综艺' ,'电视剧', '邵氏','电影']
    labels_num = len(all_labels)    
    
    # 读取用户--节目评分矩阵
    df1 = pd.read_csv('./wordsbag/dataprocess/data/week/mydata/temp_user_scores_mat.csv',sep=',',encoding='gbk',header='infer',error_bad_lines=False)    
    (m1 , n1) = df1.shape
    # 所有用户对其看过的节目的评分矩阵
    data_array1 = np.array(df1.iloc[:m1+1 , 1:])    
    # 按照"所有用户对其看过的节目的评分矩阵"的列序排列的所有用户观看过的节目名称
    items_users_saw_names1 = df1.columns[1:].tolist()

    # 读取用户观看过的节目及其所属类型的01矩阵    
    df2 = pd.read_csv('./wordsbag/dataprocess/data/week/mydata/temp_users_movies_01mat.csv',sep=',',encoding='gbk',header='infer',error_bad_lines=False)  
    (m2 , n2) = df2.shape
    data_array2 = np.array(df2.iloc[:m2 + 1, 1:])
#    print(data_array2)
    # 按照"所有用户看过的节目及所属类型的01矩阵"的列序排列的所有用户观看过的节目名称
    #items_users_saw_names2 = np.array(df2.iloc[:m2 + 1, 0]).tolist()   #此句语句得不到节目名称
    items_users_saw_names2 = np.array(df2.iloc[:m2 + 1, 0]).tolist()
    
    # 为用户看过的节目建立节目画像
    items_users_saw_profiles = createItemsProfiles(data_array2, all_labels, items_users_saw_names2)
    
    # 建立用户画像users_profiles和用户看过的节目集items_users_saw
    (users_profiles, items_users_saw) = createUsersProfiles(data_array1, all_users_names, items_users_saw_names1, all_labels, items_users_saw_profiles)


    # 读取备选节目及其所属类型的01矩阵    
    df3 = pd.read_csv('./wordsbag/dataprocess/data/week/mydata/temp_movies_01mat.csv',sep=',',encoding='gbk',header='infer',error_bad_lines=False)  
    (m3 , n3) = df3.shape
    data_array3 = np.array(df3.iloc[:m3+1, 1:])
    # 按照"备选推荐节目集及所属类型01矩阵"的列序排列的所有用户观看过的节目名称
    items_to_be_recommended_names = np.array(df3.iloc[:m3 + 1, 0]).tolist()

   # 为备选推荐节目集建立节目画像
    items_to_be_recommended_profiles = createItemsProfiles(data_array3, all_labels, items_to_be_recommended_names)

    #开始推荐
    for user in all_users_names:
         print("给用户id为 %s 的推荐节目如下:" % user)
         recommend_items = contentBased(users_profiles[user], items_to_be_recommended_profiles, items_to_be_recommended_names, all_labels, items_users_saw[user])
         printRecommendedItems(recommend_items, 5)
         print('该用户推荐任务完成。')
         print( )
          

 运行结果如下:

给用户id为 3 的推荐节目如下:
节目名:父母爱情, 推荐指数:0.215453
节目名:奔跑吧, 推荐指数:0.171533
节目名:一站到底, 推荐指数:0.171533
节目名:平民英雄, 推荐指数:0.171533
节目名:向往的生活, 推荐指数:0.171533
该用户推荐任务完成。

给用户id为 13 的推荐节目如下:
节目名:奔跑吧兄弟, 推荐指数:0.630852
节目名:逃学英雄传, 推荐指数:0.630852
节目名:非诚勿扰, 推荐指数:0.565759
节目名:生财有道, 推荐指数:0.472502
节目名:家庭幽默录像, 推荐指数:0.446079
该用户推荐任务完成。

给用户id为 23 的推荐节目如下:
节目名:档案, 推荐指数:0.327783
节目名:欢乐颂, 推荐指数:0.293158
节目名:温暖的弦, 推荐指数:0.293158
节目名:繁星四月, 推荐指数:0.293158
节目名:人间至味是清欢, 推荐指数:0.293158
该用户推荐任务完成。

该实例的实现要在前几天文章的前提下进行,原始数据文件的格式很重要。

转载:https://blog.csdn.net/WuchangI/article/details/80160566

好的,以下是基于C4.5算法使用Python实现的示例代码: ```python import numpy as np import pandas as pd class C45: """ C4.5算法实现类 """ def __init__(self, epsilon=0.1): self.epsilon = epsilon # 阈值 def calc_shannon_ent(self, data): """ 计算数据集的熵 :param data: 数据集 :return: 熵 """ n = len(data) label_counts = {} for row in data: label = row[-1] if label not in label_counts: label_counts[label] = 0 label_counts[label] += 1 shannon_ent = 0.0 for key in label_counts: prob = float(label_counts[key]) / n shannon_ent -= prob * np.log2(prob) return shannon_ent def split_data(self, data, axis, value): """ 按照给定特征划分数据集 :param data: 待划分的数据集 :param axis: 划分数据集的特征的索引 :param value: 需要返回的特征的值 :return: 划分后的数据集 """ ret_data = [] for row in data: if row[axis] == value: reduced_row = row[:axis] reduced_row.extend(row[axis + 1:]) ret_data.append(reduced_row) return ret_data def choose_best_feature(self, data): """ 选择最好的数据集划分方式 :param data: 数据集 :return: 最好的划分方式的特征索引 """ num_features = len(data[0]) - 1 base_entropy = self.calc_shannon_ent(data) best_info_gain = 0.0 best_feature = -1 for i in range(num_features): feat_list = [row[i] for row in data] unique_vals = set(feat_list) new_entropy = 0.0 for value in unique_vals: sub_data = self.split_data(data, i, value) prob = len(sub_data) / float(len(data)) new_entropy += prob * self.calc_shannon_ent(sub_data) info_gain = base_entropy - new_entropy if info_gain > best_info_gain: best_info_gain = info_gain best_feature = i return best_feature def majority_cnt(self, label_list): """ 统计类别出现的次数,返回出现次数最多的类别 :param label_list: 类别列表 :return: 出现次数最多的类别 """ label_counts = {} for vote in label_list: if vote not in label_counts: label_counts[vote] = 0 label_counts[vote] += 1 sorted_label_counts = sorted(label_counts.items(), key=lambda x: x[1], reverse=True) return sorted_label_counts[0][0] def create_tree(self, data, labels): """ 创建决策树 :param data: 数据集 :param labels: 标签列表 :return: 决策树 """ class_list = [row[-1] for row in data] # 如果类别完全相同则停止划分 if class_list.count(class_list[0]) == len(class_list): return class_list[0] # 遍历完所有特征时返回出现次数最多的类别 if len(data[0]) == 1: return self.majority_cnt(class_list) # 选择最好的数据集划分方式 best_feat = self.choose_best_feature(data) best_feat_label = labels[best_feat] my_tree = {best_feat_label: {}} del (labels[best_feat]) feat_values = [row[best_feat] for row in data] unique_vals = set(feat_values) for value in unique_vals: sub_labels = labels[:] my_tree[best_feat_label][value] = self.create_tree(self.split_data(data, best_feat, value), sub_labels) return my_tree ``` 以上是一个基于C4.5算法的决策树实现示例,可以通过调用该类的`create_tree`方法来创建决策树。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值