首页 > 解决方案 > 如何计算 pandas/sklearn 中一列中不同子类别之间的余弦相似度?(基于知识的推荐)

问题描述

我正在尝试创建一个根据用户输入推荐护肤品的程序。

期望的结果:

我想遍历 data['category'] 列下的每个子类别,并返回得分最高的产品名称(data['name'])。我确信解决方案相对简单,但我对 pandas 很陌生,并且已经研究了几天。

问题:

目前,当我在运行推荐函数(这一行print(data['name'].iloc[indices])后返回数据时,它只返回子类别“清洁剂”中的项目。理想情况下,它将返回所有具有最高相似性的产品,但即使我编辑此行score = score[0:15]以显示所有结果,它也只显示清洁剂。这可能是我如何计算相似度的问题

可能的解决方案:

我认为这个解决方案非常接近我想要的。但是,我似乎无法弄清楚如何用我的程序来实现它。以示例的方式通过 cosine_similarity 运行输入,会返回错误“您需要使用 a.reshape(-1, 1) 进行整形”,但重新整形输入也不起作用,因为它是字符串列表。

我想我在问,我如何达到我想要的结果。那 ^ 解决方案接近吗?我离基地很远吗?

如果您想自己运行它来测试结果,这也是我的 csv 文件(别担心,它的压缩版本非常小)https://pastebin.com/5iz8nxat

    import numpy as np
    import pandas as pd
    from ast import literal_eval
    from sklearn.metrics.pairwise import cosine_similarity
    from sklearn.feature_extraction.text import CountVectorizer

    data = pd.read_csv('skin_recs.csv')
    data = data[['category','skin_types','concern','sensitive','name','details']]

    data['skin_types'] = data['skin_types'].fillna('[]')
    data['concern'] = data['concern'].fillna('[]')
    #convert to python dict
    data['skin_types'] = data['skin_types'].apply(literal_eval)
    data['concern'] = data['concern'].apply(literal_eval)
    #grab all skin types & concerns
    data['skin_types'] = data['skin_types'].apply(lambda x: [i['name'].lower() for i in x] if isinstance(x, list) else [])
    data['concern'] = data['concern'].apply(lambda x: [i['name'].lower() for i in x] if isinstance(x, list) else [])
    #remove spaces
    data['skin_types'] = data['skin_types'].apply(lambda x: [i.replace(' ', '') for i in x])
    data['concern'] = data['concern'].apply(lambda x: [i.replace(' ', '') for i in x])

    s = data.apply(lambda x: pd.Series(x['skin_types']), axis=1).stack().reset_index(level=1,drop=True)
    s.name = 'type'
    data = data.drop('skin_types', axis=1).join(s)
    s = data.apply(lambda x: pd.Series(x['concern']), axis=1).stack().reset_index(level=1,drop=True)
    s.name = 'goal'
    data = data.drop('concern', axis=1).join(s)

    data['metadata'] = data.apply(lambda x : ''.join(x['type']) + ', ' + ''.join(x['goal']), axis = 1)

    vectorizer = CountVectorizer(stop_words='english')
    vect_matrix = vectorizer.fit_transform(data['name'])
    similarity = cosine_similarity(vect_matrix, vect_matrix)
    mapping = pd.Series(data.index,index = data['metadata'])

    def recommender(input, category):
        index = mapping[input]
        score = list(enumerate(similarity[index]))
        score = sorted(score, key=lambda x: x[0], reverse=True)
        score = score[0:15]
        indices = [i[0] for i in score]
        print(data['name'].iloc[indices])
    recommender('dry, acne', 'cleanser')

标签: pythonpandasnumpydataframescikit-learn

解决方案


推荐阅读