十七、机器学习进阶知识:推荐算法

1、推荐算法相关概念

1.1 推荐算法的发展

随着信息化的不断发展,人们从信息匮乏时代走入了信息过载时代,在这个时代,如何从大量的数据信息中获取有价值的信息成为关键问题。当用户存在明确的需求,面对大量的信息,可以直接从网络上筛选获得,但是当用户没有明确的需求,面对大量的信息则会显得有点手足无措。
由此,推荐系统便应运面生。一方面,推荐系统可以为信息消费者提供服务,帮助筛选他们潜在可能感兴趣的信息。另一方面,推荐系统同时也给信息生产者提供了途径去挖掘潜在的消费者,帮助他们实现更有效率的信息推送。推荐算法属于推荐系统中的基础算法部分,主要通过对用户信息进行分析,从而帮助用户获取倾向性更高的信息内容。

1.2 推荐系统

目前大型电子商务网站(如淘宝)、音乐播放软件(如网易云音乐)以及大型视频网站等都有内置的推荐系统。在购物网站上,当用户浏览或购买了某些物品后,经常会弹出新的物品供选择。一位客户刚在淘宝上浏览了乐高积木,马上看到系统推荐给他相关产品。为什么电子商务平台那么了解人们的行为?人们也总是很容易看到感兴趣的新闻,听到符合自己风格的音乐呢?这背后就是推荐系统平台在工作。推荐系统首先收集、处理客户的数据,通过分析客户的特征,为客户推荐最合适的商品。
推荐系统的核心工作是使用特定的信息分析技术,将项目推荐给可能感兴趣的用户。因此,了解用户的兴趣爱好是推荐系统最重要的一个环节,如何把用户的行为进行量化,得到每个用户的特征偏好,也是一个难题,IBM在研究中有提到一些可以参考的用户偏好统计方法。

用户行为类型特征作用
评分显式偏好,整数,取值是[0,n],n一般是5或10通过对物品的评分,可以精确地得到用户的偏好
投票显式偏好,布尔值,0或1通过对物品的投票,可以精确地得到用户的偏好
转发显式偏好,布尔值,0或1通过对物品的转发,可以精确地得到用户的偏好,也可以通过推理获得偏好信息
标记标签显式单词,需要进行分析获得偏好通过分析用户标签分析出用户的情感偏好
评论显式一段文字内容,需要进行文本分析获得偏好通过分析文本获取用户的情感偏好
单击、查看隐式一组用户可能感兴趣的单击、查看信息 ,分析后获得偏好单击与查看一定程度反映了用户的偏好程度
页面停留时间隐式时间信息,去噪分析后获得偏好页面停留时间一定程度反映了用户的注意力和偏好
购买显式偏好,布尔值,0或1用户的购买明确说明用户的偏好

由于推荐所针对的需求是潜在的、隐性的,所以如何评价推荐系统的性能是比较复杂的问题。在推荐系统进行推荐后,用户进行了购买,是否就能判断它是一个效能良好的推荐系统?答案是不一定。因为用户的购买行为受很多因素影响,可能来自商家广告、搜素引擎,以及推荐系统没有发现的用户实际需求。
此外,好的推荐系统不仅要准确预测用户的喜好,而且要能扩展用户视野,帮助用户发现那些他们可能感兴趣,但不那么容易被发现的物品。同时,推荐系统要将那些被埋没的长尾商品(那些原来不受到重视的销量小但种类多的产品或服务),推荐给可能会感兴趣的用户。推荐系统可以提高长尾商品的销售,这是搜索引擎无法办到的。
因此,推荐系统的性能评价需要从多个方面进行考虑,下面列出几种常见的评价方法,在实际使用时需要根据具体的应用场景进行设计。

  1. 用户信任度
    测量用户对推荐系统的信任程度非常关键,只有用户充分信任推荐系统,才会增加与推荐系统的互动,从而获得更好的个性化推荐。
  2. 预测准确度
    预测准确度度量一个推荐系统或者推荐算法预测用户行为的能力,这个指标是最重要的推荐系统评测指标。预测的准确度可以通过用户对物品的预测值与用户实际的评分、购买等行为之间的误差进行计算。
  3. 覆盖率
    覆盖率是指推荐出来的结果能不能很好地覆盖所有的商品,是不是所有的商品都有被推荐的机会。描述一个推荐系统对长尾商品的发掘能力,最简单的依据是被推荐的商品占物品总数的比例。
  4. 多样性
    良好的推荐系统不但要捕捉用户的喜好,还要能扩展用户视野,帮助用户发现那些他们可能会感兴趣的物品。
  5. 实时性
    推荐系统的实时性包括两方面:一是实时更新推荐列表满足用户新的行为变化;二是需要将新加人系统的物品推荐给用户。

由于推荐系统要解决的是非确定性的复杂问题,因此也会面临很多挑战,系统在运行过程中的常见困难如下:

  1. 冷启动问题
    冷启动问题是推荐系统最突出的问题。冷启动是指推荐系统在没有足够历史数据的情况下进行推荐。推荐系统开始运行时缺乏必要的数据,这时要求推荐系统给出让用户满意的推荐结果比较困难。
    冷启动问题主要分为以下三类。
    (1)用户冷启动:指新用户情况下,如何给新用户做个性化推荐的问题。
    (2)系统冷启动:指新系统情况下,只有物品的信息没有用户及行为,如何进行推荐。
    (3)物品冷启动:指新物品情况下,如何将新推出的物品推荐给可能感兴趣的用户。
    对于不同的冷启动同题,有不同的解决思路。
    (1)对新用户或不活跃用户,提供标准化的推荐,例如推荐热门产品,等收集足够多的用户数据后,再更换为个性化推荐。
    (2)对新注册用户,在注册时要求提供年龄、性别等个人信息,或进一步要求用户在首次登录时选择一些兴趣标签,或者请用户对一些物品进行评,。根据用户的个人信息、兴趣标签、对物品的打分,给用户推荐相关物品。
    (3)对于新访问用户,可以根据用户关联的社交网络账号,在授权的情况下导入用户在社交网站上的好友,然后给用户推荐其好友感兴趣的物品。
    (4)对于新物品,可以利用物品的名称、标签、描述等信息,将它们推荐给对相似物品感兴趣的用户。
    (5)对于系统冷启动问题,可以引人经验模型,根据已有的知识预先建立相关性矩阵。

  2. 多目标优化问题
    影响推荐系统性能的因素非常多,因此推荐系统可以看作一个多目标优化问题。怎样能综合考虑这些繁杂的影响因素,达到理想的推荐效果,也是一个有挑战的问题。

  3. 多源的异构数据
    推荐系统的数据来自于各种数据源、各种格式,例如用户信息、物品信息、用户和用户的关系,以及用户和物品的关系。数据源还经常是异构的,存在文字、网页、图片、声音、视频等丰富的格式。内容的多源和异构性都是需要解决的问题。

  4. 时效问题
    像新闻这样的产品,有时效性要求,另一方面,用户的兴趣会改变,也要进行跟踪更断,用户已经消费过的类似商品不需要再次推荐,因此推荐的结果需要保证实时性,要及时,准确,并且会依据最新的数据进行迭代更新。

1.3 常见的推荐算法

自首次提出协同过滤技术以来,推荐系统成一门独立的学科并受到广泛关注。推荐系统的核心是推荐算法,它认为用户的行为并不是随机的,而是蕴含着很多模式。因此,通过分析用户与项目之间的二元关系,基于用户历史行或相似性关系能够发现用户可能感兴趣的项目。
随着推荐系统的广泛应用,推荐算法也不断发展。目前来说,推荐算法可以粗略分为几个大类:协同过滤推荐算法、基于内容的推荐算法、基于图结构的推荐算法和混合推荐算法。
下面主要介绍协同过滤推荐算法以及基于内容的推荐算法。

2、协同过滤推荐算法

2.1 基于用户的协同过滤推荐算法

在日常中可以观察一个人朋友的喜好,从而进一步推测出此人的喜好,基于用户的协同过滤推荐算法就是基于此思想,算法基于假设:如果两个用户对一些项目的评分相似,那么他们对其他项目的评分也具有相似性,因此首先使用特定的方式找到与一个用户相似的用户集合,即“他的朋友们”,然后分析用户集合对某个项目的评分信息,从而推测出该用户对这个项目的偏好程度。
算法流程思路如下:

  1. 获取用户对物品的评分矩阵;
  2. 计算用户之间的相似度;
  3. 找出与用户U最相似的k个用户;
  4. 获取k个用户对物品i的评分;
  5. 根据相似度以及评分信息计算得到用户U对物品i的评分信息。

结合上述算法思路,基于用户的协同过滤推荐算法步骤可以归纳如下:
1、假设用户对物品的评分矩阵如下,中间部分为不同用户对不同商品的评分。

物品1物品2物品N
用户lel1el1elN
用户UeU1eU2eUN
用户VeV1eV2eV3
用户MeM1eM2eMN

2、用户之间的相似度可以通过计算距离获得,常见的距离计算方式有欧氏距离、余弦距离等。
若使用欧式距离计算,则上表中用户U和用户V的欧氏距离计算结果为:
在这里插入图片描述

欧氏距离的计算结果是一个非负数,取值为0到正无穷,距离越大,相似度越小。有时为了让相似度控制在某个范围以内,还会使用以下公式对上述欧氏距离进行转换,转换后的范围为(0,1]。
在这里插入图片描述
若使用余弦相似度作为相似度的计算方式,计算结果的取值范围为[-1,1]。上表中用户U和用户V的余弦距离计算结果为:
在这里插入图片描述
3、对用户U与其他用户之间计算得到的相似度进行排序,找出和用户U最相似的k个用户,用集合P(u,k)表示,假设目前有n个候选物品,则用户U对于候选物品i的评分可以利用相似度计算得到,计算公式如下:
在这里插入图片描述
其中N(i)表示对物品i进行评分的用户集合,v表示对物品i评分过,且和用户U相似度排名为前k的用户,r表示用户v对物品i的评分,sim表示用户u和用户v的相似度。
使用上述计算方式会计算前k个用户并取其和,有时希望计算结果和r的取值范围相同,因此会对上述计算结果进行求均值,即用户U对于候选物品i的评分计算如下:
在这里插入图片描述
最后根据计算得到的评分判断用户U对物品i的感兴趣程度,之后可做出是否推荐的行为。
下面使用具体的实例进行讲解。假设用某些用户对某些商品的评分数据如下所示,要求提取与用户U1最相似的两个用户,从而预测用户U1对商品I2的评分。

商品I1商品I2商品I3商品I4
用户U1544
用户U23232
用户U32521
用户U44354

首先使用欧式距离计算每个用户之间的相似度:
在这里插入图片描述
根据排序,和U1最相似的两个用户分别是U2和U4,然后利用他们对物品I2的评分计算U1对物品I2的评分:
在这里插入图片描述

上述通过计算获得了用户U1对物品I2的评分,但是有些时候用户的打分受到个人习惯的影响,因此在实际操作中,可以用评分减去用户打分的平均分,以减少用户评分的高低习惯对结果的影响,添加平均分思路后计算方式如下:
在这里插入图片描述

其中加号左边表示用户U的评分均值,分子部分减去的是用户v的评分均值。
之后可以先计算出U1、U2、U3以及U4的评分均值:
在这里插入图片描述
之后根据该均值计算得到用户U1对商品I2的评分信息:
在这里插入图片描述
基于用户的协同过滤算法原理简单,实现便捷,不过它仍存在一定的问题:

  1. 稀疏的用户评分数据
    大型电子商务系统中的物品非常多,每个用户买过的物品只占极少的比例,因此不同用户之间买的物品重叠性较低,算法很难为当前用户匹配到偏好相似的邻居用户,这种情况下评分矩阵中大部分数据都为空,因而评分矩阵都是稀疏的,难以处理。
  2. 系统扩展遇到的问题
    仅计算相似度的过程来说,运算量就很大。而且随着系统的影响力增加,用户的持续增加会存在突然的激增,相似性运算的复杂度会越来越高,运算时间变长使得对用户的响应时间慢,系统的扩展性受到制约。

2.2 基于物品的协同过滤推荐算法

和用户之间的相似性对比来看,物品之间的相似性相对固定,有时有些网站物品数量不多且增长缓慢,这是通过计算不同物品之间的相似度进行推荐,可以解决稀疏的用户评分数据这一问题。
基于物品的协同过滤算法基于以下假设:同一个用户对相似项目的评分存在相似性,当测算某个用户对某个项目的评分时,可以根据用户对若干相似项目的评分进行估计。
基于物品的协同过滤算法的思想本质和基于用户的协同过滤算法类似,可以使用相同的相似度计算公式然后获得某个用户对某个项目的评分信息,计算公式如下:
在这里插入图片描述
其中N(U)表示用户U评分过的物品集合,G(i,k)表示和物品i最相似的前k个物品集合,j为用户U评分过,且属于和物品i相似的前k个物品之一,r表示用户v对物品i的评分,sim表示物品i和物品j的相似度。
同样,基于下面的实例,使用基于物品的协同过滤算法计算用户U2对物品I2的评分。

商品I1商品I2商品I3商品I4
用户U1544
用户U23033
用户U32521
用户U44354

首先使用欧氏距离计算与I2与各个物品之间的相似度:
在这里插入图片描述
通过排序,可知与I2最相似的两个物品分别是I1、I3,所以使用用户对I1、I3的物品评分,预测用户U1对物品I2的评分:
在这里插入图片描述

2.3 协同过滤推荐算法实例

在遇到具体问题时,需要具体看用户、项目的数量来确定到底使用哪种协同过滤算法。如果物品数据很多,物品之间的相似度计算量就会很大;同样的,用户数据很多,用户之间的相似度计算量也会很大,一个简单的思路就是比较用户和物品的数量,取数量较少、增长较缓慢的进行计算。
下面结合具体的实例进行协同过滤推荐算法的介绍。本例子采用著名的电影数据集MoviesLens-100k数据集,该数据包含943个用户为精选的1682部电影给出的100000个电影评分,该数据集中主要的数据文件如下:
u.data文件:列数据依次为user_id,movie_id,rating,unix_timestamp,数据列以tab分隔。
u.item文件:列数据依次为movie_id,title,release_data,video_release_date,imdb_url(电影ID,片名,上映时间和IMDB链接)。此外用布尔值的组合标识每部电影的类型,包括动作、探险、动画等,详细内容可查看数据集的说明文件readme.txt。数据以“|”符号分隔。
u.user:列数据依次为user_id,age,occupation,zip_code。
注:数据集及详细代码解释可查看文末链接。

import pandas as pd
# 读入数据
u_cols = ['user_id', 'age', 'sex', 'occupation', 'zip_code']
# 读取u.user文件
users = pd.read_csv('ml-100k/u.user', sep='|', names=u_cols,encoding='latin-1')
print(users)
r_cols = ['user_id', 'movie_id', 'rating', 'unix_timestamp']
# 读取u.data文件
ratings = pd.read_csv('ml-100k/u.data', sep='\t', names=r_cols,encoding='latin-1')
print(ratings)
m_cols = ['movie_id', 'title', 'release_date', 'video_release_date', 'imdb_url'] 
# 读取u.item文件
movies = pd.read_csv('ml-100k/u.item', sep='|', names=m_cols, usecols=range(5),encoding='latin-1') 
print(movies)

之后分别使用基于用户的协同过滤算法以及基于电影项目的协同过滤算法进行电影推荐,并对算法效率进行评估。

import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import pairwise_distances

#user-based/item-based预测函数
def predict(scoreData, similarity, type='user'):        
    # 1. 基于物品的推荐
    if type == 'item':        
        #评分矩阵scoreData乘以相似度矩阵similarity,再除以相似度之和
        predt_Mat = scoreData.dot(similarity) / np.array([np.abs(similarity).sum(axis=1)])    
    elif type == 'user':        
    # 2. 基于用户的推荐
# 计算用户评分均值,减少用户评#分高低习惯影响
        user_meanScore = scoreData.mean(axis=1)  
        score_diff = (scoreData - user_meanScore.reshape(-1,1))  #获得评分差值 
        #推荐结果predt_Mat: 等于相似度矩阵similarity乘以评分差值矩阵
# score_diff,再除以相似度之和,最后加上用户评分均值user_meanScore。
        predt_Mat = user_meanScore.reshape(-1,1) + similarity.dot(score_diff) / np.array([np.abs(similarity).sum(axis=1)]).T
    return predt_Mat
 
#步骤1.读数据文件
print('step1.Loading dataset...')
r_cols = ['user_id', 'movie_id', 'rating', 'unix_timestamp']
scoreData = pd.read_csv('ml-100k/u.data', sep='\t', names=r_cols,encoding='latin-1')
print('  scoreData shape:',scoreData.shape)

#步骤2.生成用户-物品评分矩阵
print('step2.Make user-item matrix...')
n_users = 943
n_items = 1682
data_matrix = np.zeros((n_users, n_items))
for line in range(np.shape(scoreData)[0]):    
    row=scoreData['user_id'][line]-1  
    col=scoreData['movie_id'][line]-1  
    score=scoreData['rating'][line]    
    data_matrix[row,col] = score
print('  user-item matrix shape:',data_matrix.shape)

#步骤3.计算相似度
print('step3.Computing similarity...')
#使用pairwise_distances函数,简单计算余弦相似度
user_similarity = pairwise_distances(data_matrix, metric='cosine')
item_similarity = pairwise_distances(data_matrix.T, metric='cosine') #T转置转变计算方向
print('  user_similarity matrix shape:',user_similarity.shape)
print('  item_similarity matrix shape:',item_similarity.shape)

#步骤4.使用相似度进行预测
print('step4.Predict...')    
user_prediction = predict(data_matrix, user_similarity, type='user')
item_prediction = predict(data_matrix, item_similarity, type='item')
print('ok.')

在这里插入图片描述

程度运行后获得了两个预测结果矩阵,其中user_prediction是基于用户的协同过滤的推荐结果,item_prediction是基于物品的协同过滤的推荐结果,可以通过以下代码查看部分信息。

print('step5.Display result...')  
print('------------------------')  
print('(1)UBCF predict shape',user_prediction.shape)
print('  real answer is:\n',data_matrix[:5,:5])
print('  predict result is:\n',user_prediction[:5,:5])
print('(2)IBCF predict shape',item_prediction.shape)
print('  real answer is:\n',data_matrix[:5,:5])
print('  predict result is:\n',item_prediction[:5,:5])

在这里插入图片描述

之后使用sklearn模块提供的mean_square_error()函数计算MSE,然后利用sqrt函数计算获得RMSE误差平方根。

print('step6.Performance evaluation...')    
from sklearn.metrics import mean_squared_error
from math import sqrt
#计算算法的MSE误差
def rmse(predct, realNum):
    #去除无效的0值 
    predct = predct[realNum.nonzero()].flatten() 
    realNum = realNum[realNum.nonzero()].flatten()
    return sqrt(mean_squared_error(predct, realNum))
print('U-based MSE = ', str(rmse(user_prediction, data_matrix)))
print('M-based MSE= ', str(rmse(item_prediction, data_matrix)))

在这里插入图片描述
从结果可以看出,基于用户的协同过滤算法的误差值约为2.96,而基于物品的协同过滤算法误差值为3.39,误差较高主要是由于数据的稀疏性导致。

3、基于内容的推荐算法

基于内容的模式起源于信息检索领域,这种模式是以物品的内容为基础,推荐原理是分析系统的历史数据,提取对象的内容特征和用户的兴趣偏好。对被推荐对象,先和用户的兴趣偏好相匹配,再根据内容之间的关联程度,将关联度高的内容推荐给用户。
这里关键的环节是计算被推荐对象的内容特征和用户模型的兴趣特征二者之间的相似性。与协同过滤算法不同的地方在于,基于内容的推荐算法不需要大量用户、物品数据作为评分的基础,而是对用户评过分的物品进行文档整理,列出这些物品的标记或关键词列表。目前基于内容的推荐算法大多使用在大量文本信息的场合,如新闻推荐。
推荐时会把这些产品的文本信息关键字提取出来形成一个标签列表,并将之前对用户喜欢过的物品进行整理得到的标签与新物品标签进行比对。
例如,对微博用户进行广告推荐,首先要通过用户发言提炼出用户的兴趣关键字,接下来对广告内容进行分析,提取出广告内容的关键词。二者相匹配的话则进行推荐。对于这样的文本数据,可以配合使用 TF-IDF 频率数据。假设某用户的标签为游泳、教练、体能、挑战,而某体育用品的标签是训练、体能、游泳,二者能够匹配上,那么就能够将该体育用品定向推荐给此用户。
基于内容的推荐算法的主要优势如下。

  1. 不需要大量数据。只要用户产生了初始的历史数据,就可以开始进行推荐的计算,而且可以期待准确性。
  2. 方法简单、有效,推荐结果直观,容易理解,不需要领域知识。
  3. 不存在稀疏问题。

基于内容的推荐算法的缺点如下。

  1. 对物品内容进行解析时,受到对象特征提取能力的限制。例如,图像、视频、音频等产品资源没有有效的特征提取方法。即使是文本资源,提取到的特征也只能反映资源的一部分内容。
  2. 推荐结果相对固化,难发现新内容。只有推荐对象的内容特征和用户的兴趣偏好匹配才能获得推荐。用户仅获得跟以前类似的推荐结果,很难为用户发现新的感兴趣的信息。
    下面结合具体的实例对基于内容的推荐算法进行介绍。

问题描述:数据集hot-spicy pot.cvs中包含两列数据,一列是菜品的名称,一列是菜品的特征,如脆的、甜的、辣的等记录。现在要求根据输入的某个材料推荐和其最相似的前10个菜品。
注:数据集及详细代码解释可查看文末链接。

import pandas as pd
from numpy import *
from sklearn.feature_extraction.text import TfidfVectorizer

#1.读取数据 
print('Step1:read data...')
food=pd.read_csv('hot-spicy pot.csv')
food.head(10)

#2.将菜品的描述构造成TF-IDF向量
print('Step2:make TF-IDF...')
tfidf=TfidfVectorizer(stop_words='english')
tfidf_matrix=tfidf.fit_transform(food['taste'])
tfidf_matrix.shape

#3.计算两个菜品的余弦相似度 
print('Step3:compute similarity...')
from sklearn.metrics.pairwise import pairwise_distances
cosine_sim=pairwise_distances(tfidf_matrix,metric="cosine")

#推荐函数,输出与其最相似的10个菜品 
def content_based_recommendation(name,consine_sim=cosine_sim):
    idx=indices[name]
    sim_scores=list(enumerate(cosine_sim[idx]))
    sim_scores=sorted(sim_scores,key=lambda x:x[1])
    sim_scores=sim_scores[1:11]
    food_indices=[i[0]for i in sim_scores]
    return food['name'].iloc[food_indices]

#4.根据菜名及特点进行推荐
print('Step4:recommend by name...')
#建立索引,方便使用菜名进行数据访问 
indices=pd.Series(food.index,index=food['name']).drop_duplicates()
result=content_based_recommendation("celery")
result

在这里插入图片描述
电影推荐、菜品推荐数据集以及详细代码注释

  • 28
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
《Spark机器学习进阶实战》是一本关于使用Spark框架进行高级机器学习实践的教程。它涵盖了许多Spark的高级特性和机器学习算法,可以帮助读者更深入地理解和应用这两个领域。 这本书首先介绍了Spark的基本概念和编程模型,包括RDD、DataFrame和Spark SQL等。然后,它详细讲解了Spark在机器学习领域的应用,涉及到了常见的机器学习算法,如线性回归、逻辑回归、决策树、随机森林等。此外,它还介绍了特征工程、模型评估和调参等相关主题。 这本书特别强调了如何利用Spark的分布式计算能力来处理大规模数据和训练复杂的机器学习模型。它介绍了Spark的并行计算机制和任务调度策略,以及如何使用Spark对数据进行预处理和特征提取。此外,它还介绍了如何使用Spark MLlib库进行机器学习模型的训练和评估。 这本书还包含了大量的实际案例和示例代码,读者可以通过实践来加深对Spark和机器学习的理解。此外,书中还涵盖了优化技巧和调试方法,帮助读者解决实际问题。 总之,《Spark机器学习进阶实战》是一本全面介绍Spark和机器学习的实战教程,它对于那些想要深入学习和应用这两个领域的读者来说是一本很有价值的资料。无论是对于初学者还是有经验的开发者来说,这本书都能提供实用的知识和技能,帮助读者在实践中取得更好的结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七层楼的疯子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值