我正在探索python中的推荐系统,到目前为止,我已经使用KNN模型来建议采用“您也购买了...等用户”的品牌。我的数据表中每个客户都有一行,每个品牌都有一列,其中填充了1
或0
,以表明客户是否购买了该品牌。
我现在想将其推广到产品级别的建议,但仍在努力寻找这种方法的扩展方式。我尝试了相同的方法,但是无法使用足够大的查询来查询数据库(BigQuery)以为每个产品(10,000+)生成一列。
例如,我的来源是导出到BigQuery的Google Analytics(分析)每日数据,我将根据以下示例创建输入数据:
SELECT
customDimension.value AS UserID,
MAX(IF(UPPER(hits_product.productSKU) LIKE "SKU1",1,0)) AS SKU1,
MAX(IF(UPPER(hits_product.productSKU) LIKE "SKU2",1,0)) AS SKU2,
MAX(IF(UPPER(hits_product.productSKU) LIKE "SKU3",1,0)) AS SKU3
# plus 10,000 more...
FROM
`PROJECT.DATASET.ga_sessions_20*` AS t
CROSS JOIN
UNNEST (hits) AS hits
CROSS JOIN
UNNEST(t.customdimensions) AS customDimension
CROSS JOIN
UNNEST(hits.product) AS hits_product
WHERE
parse_DATE('%y%m%d',
_table_suffix) BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 1 day)
AND DATE_SUB(CURRENT_DATE(), INTERVAL 1 day)
AND customDimension.index = 2
AND customDimension.value NOT IN ("true","false","undefined")
AND customDimension.value IS NOT NULL
AND hits.eventInfo.eventCategory = 'Ecommerce'
AND hits.eventInfo.eventAction = 'Purchase'
GROUP BY
UserID
为每个SKU用一行运行该查询会产生错误:
查询太大。查询的最大长度为256.000K个字符,包括注释和空格字符。
在这种情况下,人们将如何创建产品级别的建议?正常情况下,数据是否以不同的形式被摄取到python中并转化为代码中的maxrix?
这时我很沮丧,所以任何建议都将受到欢迎。
答案 0 :(得分:1)
我不确定如何在BigQuery(或SQL的任何方言)中有效地创建所需的1-0(单热式)编码,但我绝对知道如何在Python中进行编码。
聚集这些数据以供在Python中使用的最有效方法可能是执行以下操作...
您的BigQuery表似乎遵循以下结构:
在this question中,您可以使用以下方法将每个SKU聚合为一行:
SELECT UserID, STRING_AGG(SKU) AS SKU_string FROM my_transactions_table GROUP BY UserID
这应该给你(从上面的示例表中获得):
从那里开始,很容易在Python中使用这些数据:
>>> import pandas as pd
>>> df = pd.read_csv('~/Desktop/test.csv', sep='\t')
>>> df
UserID SKU_string
0 1 a,b,c
1 2 b,b
2 3 c,b,a
我们可以使用scikit-learn的CountVectorizer类为每个用户计算每种产品的出现次数:
>>> from sklearn.feature_extraction.text import CountVectorizer
>>> vec = CountVectorizer(tokenizer=lambda x: x.split(','))
>>> X = vec.fit_transform(df['SKU_string'])
>>> X
<3x3 sparse matrix of type '<class 'numpy.int64'>'
with 7 stored elements in Compressed Sparse Row format>
>>> pd.DataFrame(X.toarray(), columns=vec.get_feature_names())
a b c
0 1 1 1
1 0 2 0
2 1 1 1
如果愿意,可以将该矩阵重新连接到DataFrame以及您可能已经选择的其他用户元数据:
>>> df = df.join(pd.DataFrame(X.toarray(), columns=['product_{}'.format(x) for x in vec.get_feature_names()]))
>>> df
UserID SKU_string product_a product_b product_c
0 1 a,b,c 1 1 1
1 2 b,b 0 2 0
2 3 c,b,a 1 1 1
但是,如果您有多少不同的产品,我很可能会建议您这样做。 10,000种产品可创建10,000个其他非稀疏列,如果您有很多客户,这些列可能会占用大量内存。
此外,如果您要将那个X
对象(一个scipy.sparse.csr_matrix
)严格转换为零编码,请尝试以下操作:
>>> import numpy as np
>>> import scipy.sparse
>>> def booleanize_csr_matrix(mat):
... ''' Convert sparse matrix with positive integer elements to 1s '''
... nnz_inds = mat.nonzero()
... keep = np.where(mat.data > 0)[0]
... n_keep = len(keep)
... result = scipy.sparse.csr_matrix(
... (np.ones(n_keep), (nnz_inds[0][keep], nnz_inds[1][keep])),
... shape=mat.shape
... )
... return result
...
>>> pd.DataFrame(booleanize_csr_matrix(X).toarray(), columns=vec.get_feature_names())
a b c
0 1.0 1.0 1.0
1 0.0 1.0 0.0
2 1.0 1.0 1.0
从那里开始,您可以使用各种算法根据用户推荐商品...您可能会看sklearn.metrics.pairwise.cosine_similarity
来衡量每个用户的购买向量之间的角度。
答案 1 :(得分:0)
通常,当我们的sql查询看起来更像服务器日志(很长很长)时,可能是时候重新考虑数据的策略和结构以及尝试围绕它设计方法了。
在您的特定情况下,您尝试使用绝对元素构造查询,这通常不是一个好习惯。因此,您需要做的就是将您的skus(全部)转储到BigQuery表中。完成此操作后,您就可以在BigQuery中使用ARRAYS
来生成一次性编码(不是这样)。以下是使用公共GA数据的简短示例:
with listskus as (
-- this is fake data.
-- replace it with your sku listing query (i.e. select sku as listsku from myskutable)
select
listsku from
unnest(generate_array(0, 11000, 1))
as listsku
),
data as (
select
visitId as userid,
array(
(
select
if(p.productSKU like concat('%',cast(l.listsku as string)), 1, 0)
from unnest(hits.product) p
left outer join listskus l on 1=1
)
) as onehotvector
from
`bigquery-public-data.google_analytics_sample.ga_sessions_20170801`,
unnest(hits) hits
)
select userid, onehotvector from data