美文网首页
Pandas和NumPy(第二部分)

Pandas和NumPy(第二部分)

作者: Python_Camp | 来源:发表于2022-04-06 15:49 被阅读0次

    了解更多关于数据科学的高级Pandas和NumPy的信息(第二部分)
    Pandas和NumPy(第二部分) Cont.......
    欢迎回到第二部分的文章。希望大家喜欢那里的内容,这里将继续保持同样的节奏,在这个空间里学习更多的东西。
    我们在第一部分中已经介绍了重塑数据框架和组合数据框架。

    与分类数据一起工作。
    首先,试着理解什么是给定数据集中的分类变量。
    分类变量是一组数值,它可以很容易地被标记,并且包含明确的可能值。 它可以是数字或字符串。比方说,地点、职务、学生的年级、年龄、性别,以及更多的例子。
    不过,我们还是可以将分类数据分为顺序数据和名义数据。
    有序数据
    这些分类变量有适当的内在顺序(如年级、职务)。
    名义数据
    这与顺序数据正好相反,所以我们不能期望有一个固有的顺序 🙂
    连续数据
    连续变量/特征有无限多的值,有一定的界限,总是可以是数字或日期/时间数据类型。

    实际上,我们要对它们进行 "编码",并在数据科学/机器学习生命周期过程中进行进一步分析。
    我们知道,在数据科学领域,70%-80%的努力将被用于EDA过程。因为清洗和准备数据是主要的任务,然后我们才能准备稳定的模型选择并最终确定它。
    其中,将分类数据转换为数字数据的过程是一个不可避免的必要活动,这个活动被称为编码。
    编码技术

    One Hot Encoding
    Dummy Encoding
    Label Encoding
    Ordinal Encoding
    Target Encoding
    Mean Encoding

    One-Hot Encoding
    虚数编码
    标签编码
    顺序编码
    目标编码
    平均值编码
    单热编码

    我们知道,FE是将给定的数据转化为合理的形式,这更容易解释,使数据更透明,以帮助建立模型。
    同时,创造新的特征来增强模型,在这方面,一热编码方法开始发挥作用。

    这种技术可以在特征是名义上的时候使用。
    在一热编码中,对于分类特征的每一级,我们都会创建一个新的变量。(特征/列)
    类别可以用二进制变量0或1来映射,基于存在或不存在。

    虚数编码
    这个方案类似于One Hot Encoding编码。
    分类编码方法将分类变量转化为二进制变量(也称为虚拟变量)。
    假人编码方法是一个超过One Hot Encoding编码的改进版本。
    它使用N-1个特征来代表N个标签/类别。

    One Hot Encoding

    data=pd.DataFrame({“Fruits”:”Apple”,”Banana”,”Cherries”,”Grapes”,”Mango”,”Banana”,”Cherries”,”Grapes”,“Mango”,”Apple”]})
    data
    #Create object for one-hot encoding
    import category_encoders as ce
    encoder=ce.OneHotEncoder(cols=’Fruits’,handle_unknown=’return_nan’,return_df=True,use_cat_names=True)
    data_encoded = encoder.fit_transform(data)
    data_encoded
    

    日期时间数据
    当你处理数据和时间数据类型时,我们可以使用DateTime库,它与pandas一起成为Datetime对象。在to_datetime()函数的基础上,帮助我们将多个DataFrame列转换成一个DateTime对象。

    Python datetime类的列表
    datetime 操作日期和时间 - 月、日、年、小时、秒、微秒。
    date 单独操作日期--月、日、年。
    time 操作时间--小时、分钟、秒、微秒。
    timedelta 测量日期和时间。
    tzinfo 处理时区问题。

    转换数据类型
    正如我们所知,转换数据类型在所有编程语言中都是常见的。Python在这方面并不例外。Python提供了类型转换函数,将一种数据类型转换为另一种。
    Python中的类型转换。
    明确的类型转换。 在开发过程中,开发者将根据他们的要求在程序流程中编写代码来改变数据的类型。
    隐式类型转换。 Python具有自动转换类型的能力,不需要任何人工参与。
    显式类型转换
    代码

    Python中的类型转换

    # Type conversion in Python
    strA = “1999” #Sting type
    # printing string value converting to int
    intA = int(strA,10)
    print (“Into integer : “, intA)
    # printing string converting to float
    floatA = float(strA)
    print (“into float : “, floatA)
    Output
    Into integer : 1999into float : 1999.0
    # Type conversion in Python
    # initializing string
    strA = “Welcome”
    ListA = list(strA)
    print (“Converting string to list :”,(ListA))
    tupleA = tuple(strA)
    print (“Converting string to list :”,(tupleA))
    Output
    Converting string to list : [‘W’, ‘e’, ‘l’, ‘c’, ‘o’, ‘m’, ‘e’]
    
    Few other function 
    dict() : Used to convert a tuple  into a dictionary.str() : Used to convert integer into a string.
    Implicit Type Conversion
    a = 100
    print(“a is of type:”,type(a))
    b = 100.6
    print(“b is of type:”,type(b))
    c = a + b
    print(c)
    print(“c is of type:”,type(c))
    Output
    a is of type: <class ‘int’>b is of type: <class ‘float’>200.6c is of type: <class ‘float’>
    

    Python中的访问修改器。 正如我们所知,Python支持Oops。所以我们当然要有Public、Private和Protected,是的,当然要有!
    Python的访问修改是用来限制类的变量和方法的。在Python中,我们必须使用UNDERSCORE 符号来确定一个数据成员和/或类的方法的访问控制。
    公共访问修改器。
    默认情况下,所有的数据成员和成员函数都是公开的,可以从程序文件的任何地方访问。
    受保护的访问修饰符。
    如果我们想声明受保护的数据成员或成员函数,可以用一个下划线
    符号作为前缀。
    私人访问修饰符。
    如果我们想用双下划线__符号来声明私有数据成员或成员函数的前缀。

    Public Access Example
    class Employee:
    def __init__(self, name, age):
    # public data mambers
    self.EmpName = name
    self.EmpAge = age
    # public memeber function displayEmpAge
    def displayEmpAge(self):
    # accessing public data member
    print(“Age: “, self.EmpAge)
    # creating object of the class from Employee Class
    objEmp = Employee(“John”, 40)
    # accessing public data member
    print(“Name: Mr.”, objEmp.EmpName)
    # calling public member function of the class
    objEmp.displayEmpAge()
    OUTPUT
    Name: Mr. JohnAge: 40
    Protected Access Example
    Creating super class and derived class. Accessing private and public member function.
    # super class
    class Employee:
    # protected data members
    _name = None
    _designation = None
    _salary = None
    # constructor
    def __init__(self, name, designation, salary):
    self._name = name
    self._designation = designation
    self._salary = salary
    # protected member function
    def _displayotherdetails(self):
    # accessing protected data members
    print(“Designation: “, self._designation)
    print(“Salary: “, self._salary)
    # derived class
    class Employee_A(Employee):
    # constructor
    def __init__(self, name, designation, salary):
    Employee.__init__(self, name, designation, salary)
    # public member function
    def displayDetails(self):
    # accessing protected data members of super class
    print(“Name: “, self._name)
    # accessing protected member functions of superclass
    self._displayotherdetails()
    # creating objects of the derived class
    obj = Employee_A(“David”, “Data Scientist “, 5000)
    # calling public member functions of the class
    obj.displayDetails()
    OUTPUT
    Name: David
    Designation: Data Scientist
    Salary: 5000
    

    希望我们学到了这么多东西,对大家非常有用,并且必须涵盖Numpy,这里我就不多说了,在下一篇文章中继续。谢谢你的时间和阅读,请留下你的评论。我们将很快联系您!
    在那之前,再见,很快就会见到你 - 干杯!

    Starbucks 预测

    星巴克销售分析 - 第 1 部分
    深入了解星巴克的销售数据!
    每一个数据都在讲述一个故事!作为 Udacity 数据科学纳米学位项目的一部分,我有幸看到了星巴克的销售数据。在这个顶点项目中,我可以自由地以自己的方式分析数据。所以,在这个博客中,我将尝试解释我做了什么。

    数据集概述
    创建数据是为了概述以下内容:
    观察人们基于不同促销优惠的购买决定。
    提供三种类型的优惠:BOGO(买一送一)、折扣和信息。我想看看这些优惠对购买的影响。
    最后,我想看看这些优惠如何影响特定的人群。
    数据集中有3个文件:
    profile.json
    奖励计划用户(17000 个用户 x 5 个字段)
    性别:(分类)M、F、O 或 null
    年龄:(数字)缺失值编码为 118
    id:(字符串/哈希)每个用户的 id。
    become_member_on:(日期)格式 YYYYMMDD
    收入:(数字)
    投资组合.json
    在 30 天测试期间发送的报价(10 个报价 x 6 个字段)
    奖励:(数字)根据花费的金额奖励的金额
    渠道:(列表)网络、电子邮件、移动、社交
    难度:(数字)获得奖励所需花费的金钱
    持续时间:(数字)要约打开的时间,以天为单位
    offer_type:(字符串)BOGO,折扣,信息
    id:(字符串/哈希)报价的ID
    成绩单.json
    事件日志(306648 个事件 x 4 个字段)
    人:(字符串/哈希)
    事件:(字符串)收到报价、查看报价、交易、报价完成
    value:(字典)不同的值,取决于事件类型
    报价 ID:(字符串/哈希)与任何“交易”无关
    金额:(数字)在“交易”中花费的金额
    奖励:(数字)从“报价完成”中获得的金钱
    时间:(数字)测试开始后的小时数

    问题陈述
    我试图回答三个主要问题。
    基于优惠类型和人口统计的消费模式是什么?
    如何根据现有客户的消费模式向他们推荐优惠券/优惠?
    如何向新客户推荐优惠券/优惠?

    数据分析
    从portfolio.json文件中,我发现有3 种不同类型的10 个offer:BOGO、Discount、Informal。
    BOGO:对于买一送一的优惠,我们需要购买一件产品才能得到一个等于阈值的产品。
    折扣:在此优惠中,用户需要花费一定的金额才能获得折扣。
    信息性:此类优惠没有折扣或最低消费金额。
    要兑换优惠,您必须花费 0、5、7、10或 20美元。

    profile.json数据是 17000 个人的信息。数据有一些空值。通过查看数据,我们可以说有些人没有透露他们的性别、年龄或收入。这就是为什么我们在性别和收入列中有相同数量的空值,而相应的年龄列有 118 作为年龄。
    配置文件数据的分布

    图 1. 左:平均年龄与性别的分布;
    右图:年龄和收入数据的分布
    个人资料数据在性别之间具有相同的平均年龄分布。
    正如我们所看到的,年龄数据几乎是一个高斯分布(略微右偏),其中 118 是异常值,而收入数据是右偏的。

    transcript.json数据包含 17000 个唯一人员的交易详情。
    注册、交易、收到报价和查看报价4 种类型的事件
    value列包含商品 ID或交易金额。

    数据预处理
    回答第一个问题:基于优惠类型和人口统计的消费模式是什么?我将重新排列数据文件并尝试回答几个问题以回答问题 1

    子问题是:
    热门优惠有哪些?
    不同性别之间如何使用优惠?
    交易如何随性别、年龄和收入而变化?
    首先,我合并了portfolio.json、profile.json 和transcript.json文件以添加人口统计信息并提供更好的可视化信息。所以我的新数据集有以下列:

    “人”、“事件”、“价值”、“时间”、“性别”、“年龄”、“收入”、“日期”。
    此外,我将“null”性别更改为“Unknown”以使其成为新功能。
    让我们回顾一下这些列以便更好地理解:
    人(类别):17000 个独立用户。
    事件(类别):4 个独特的类别:报价已完成、报价已收到、报价已查看和交易。
    value(category/numeric):当 event = 'transaction' 时,value 为数字,否则以商品 ID 作为类别的分类。
    time(numeric): 0 是实验的开始。
    性别(类别):4 个独特的类别:男性、女性、其他和未知。
    年龄(数字):数字列,118 为未知或异常值。
    收入(数字):具有一些对应于 118 年龄的空值的数字列。
    日期:交易日期。

    有哪些受欢迎的优惠类型?
    我们可以绘制出分布式报价的百分比是 BOGO、折扣和信息性的图,最后找出接收、查看和完成的报价的百分比。
    为此,我将报价数据与交易数据(事件 = '交易')分开。

    图 2. 收到的报价与报价类型的百分比
    我们可以看到,信息报价不需要完成。虽然,BOGO 和 Discount优惠分布均匀,
    对 BOGO 优惠的浏览量超过了折扣优惠。
    但是,折扣优惠完成得更多。
    因此,折扣优惠在完成方面更受欢迎。

    不同性别之间如何使用优惠?
    由于“信息”报价没有报价完成,我们可以忽略包含“信息”报价的行以找出查看的报价和报价完成之间的关系。

    图 3 报价类型与性别
    从“按性别收到的平均报价”图中,我们看到按性别划分的每人平均收到的报价几乎相同。
    “按性别分配的报价”图显示了按性别查看的报价在收到的报价中的百分比以及在按性别收到的报价中完成的报价的百分比。
    我们看到,
    其他客户查看最多的优惠和
    男性客户查看的报价最少。
    女性客户完成的报价最多,并且,
    未知组完成的报价最少。
    可以说,如果有优惠,女性和其他性别的人兑现优惠的机会更高!

    交易如何随性别、年龄和收入而变化?
    从交易数据中,我们尝试找出性别、年龄和收入与平均交易金额的关系。

    图 4. 年龄、性别、收入对平均支出的依赖
    我们可以看到年龄和收入与支出的预期趋势。随着年龄和收入的增长,平均支出增加。
    在性别图中,我们看到女性往往花费最多,而没有人口统计数据(未知性别)的群体往往花费最少。
    年龄和平均支出之间存在正相关关系。
    人们消费更多,收入更高。

    结论
    所以,总而言之,要回答基于优惠类型和人口统计的消费模式是什么?
    可能的答案是,
    虽然 BOGO 优惠被更多人浏览,但折扣优惠在完成度方面更受欢迎。
    收到优惠后,兑换优惠的机会在女性和其他性别中更高!
    女性往往花费最多。
    支出随着年龄和收入的增加而增加。

    在本博客的第 2 部分中,我将解释,
    如何根据现有客户的消费模式向他们推荐优惠券/优惠?
    如何向新客户推荐优惠券/优惠?
    可以在此处找到此博客第 2 部分的链接。
    这个项目的 GitHub 存储库可以在这里找到。

    巴克销售分析——第 2 部分
    深入了解星巴克的销售数据!
    如果您尚未阅读此博客的第 1 部分,请点击此处的链接。在第 2 部分中,我将尝试解决剩下的两个问题:
    如何根据现有客户的消费模式向他们推荐优惠券/优惠?
    如何向新客户推荐优惠券/优惠?
    我将向您展示如何构建一个推荐系统来为每个优惠推荐理想的用户。
    换句话说,我的目标是向现有用户推荐最好的报价。在这个系统中,我们选择一个现有的报价并为该报价推荐前 n 个用户。但这可以很容易地扩展到类似的未来报价。
    在这样做之前,我们需要记住一些事情。
    我们需要识别在没有实际打开报价的情况下完成报价的用户。我们不需要向这些用户发送优惠,因为他们很可能并不关心优惠。
    如果用户平均花费超过 20 美元,他们很可能不会依赖优惠。
    由于我们的报价价值为 5 美元、7 美元、10 美元和 20 美元,我们可以得出一个一般规则,即如果用户平均花费 15 美元,我们可以向他们推荐 20 美元的报价以多花一些钱。
    最后,我们也想为新用户提出建议。为此,我们可以根据人口统计数据和其他特征训练 ML 模型来预测用户将花费的金额。根据价值,我们可以向他们推荐或不推荐!(例如,如果用户预计花费超过 20 美元,或者非常低于 5 美元,我们不会发送报价)。

    如何根据现有客户的消费模式向他们推荐优惠券/优惠?
    BOGO 和折扣优惠有两种可能性,
    我们可以设置查看的报价/收到的报价的阈值比率,并说如果该值超过阈值百分比,他们就有更好的机会打开报价。
    同样,我们可以设置完成报价/查看报价的阈值比率,并说如果该值超过阈值百分比,他们就有更好的机会完成报价。
    但是有一个问题!我们可以让人们在没有打开报价的情况下完成报价。在这种情况下,完成报价/查看报价的比率将大于 1。我们不需要向他们发送报价,因为无论如何他们很可能会购买产品。所以,我们也需要设置一个上限!
    最后,我们可以使用信息性报价数据并构建一个独立的推荐系统,而不是 BOGO 和折扣报价,因为不需要为此类报价花费任何费用。
    如何构建推荐系统?
    对于 BOGO 和折扣优惠数据,
    我们将使用基于排名的推荐
    将有基于用户用户的协同过滤,我们将为每个优惠推荐前 n 个用户。
    我们将使用 ML为新用户提供基于内容的推荐。我们将根据人口统计数据训练一个模型来预测平均支出。根据该值,我们将推荐报价。
    对于信息报价,
    我们将使用基于排名的推荐。由于此类别中只有两个优惠,我们将仅预测前 n 个用户的类似新优惠。
    让我们看一下信息报价数据和 BOGO/折扣报价数据。

    no_info_data
    包含 BOGO 和折扣优惠,info_data
    仅包含信息优惠。

    现在,从上表中,如果我们查看“no_info_data”中已完成/查看和查看/接收的数据列,并查看“info_data”中的查看/接收数据列,我们可以估计要使用的阈值。

    no_info_data:已完成/已查看的平均值为0.74,1.5是数据的第 90 个百分位数。查看/接收的平均值为 0.77,1是数据的第 90 个百分位数。

    info_data:查看/接收的平均值为0.71,1 是数据的第 75 个百分位。

    基于排名的推荐:
    在这种方法中,我们将为 BOGO/折扣优惠返回 n 个 top person,为信息性优惠返回 n top person。他们将有资格获得未来的类似优惠。

    为了首先获得 n 个顶级非信息用户,我们将根据“已查看/已接收”和“已完成/已查看”列中的某些阈值过滤掉用户。然后我们将看看他们的平均交易价值。如果值大于 20,那么我们将丢弃该用户,因为最大的优惠是购买 20 美元可享受 5 美元的折扣。所以用户并不关心优惠。
    BOGO/折扣优惠:

    get_n_top_info_user(topn = 5)
    >>> array(['23d67a23296a485781e69c109a10a1cf',
           '6dba14f698ae4030ab7354cd5cfe7119',
           'eece6a9a7bdd4ea1b0f812f34fc619d6',
           '05bbe7decb6d43b684221df448979612',
           '116b28e2983c44039eb8b20292742c94'], dtype=object)
    
    get_n_top_non_info_user(topn = 5)
    >>> array(['d167940f7af04f4681daaa6d1bfd80a1',
           'a2633655a62e4287a3b651d926a774a6',
           '4d4216b868fe43ddb9c9f0b77212c0cb',
           'bb465e90882143b6a49f99d9d810dc3f',
           '17b29dcb0f924294a0d1de2ca59c763f'], dtype=object)
    

    用于 BOGO/折扣数据的基于用户的协作过滤
    既然我们已经为新优惠创建了基于排名的推荐,那么如果我们想将现有优惠发送给尚未收到某些优惠的现有用户怎么办?

    我们将尝试为每个现有优惠找到前 n 个用户。为此,我们将创建一个 user_item 矩阵。
    我们将重新格式化 offer_data 数据框,以用户为列,商品为行。
    每个用户只能在每一列中出现一次。

    每个优惠只能显示在一行中。
    如果用户已与优惠进行交互,则在用户列与该优惠行相交的位置放置一个 1。用户与优惠互动的次数无关紧要,用户与优惠互动的所有条目都应为 1。

    如果用户没有与优惠进行交互,则在用户列与该优惠行相交的位置放置一个零。
    我们将编写一个函数,它应该获取一个人并提供与该用户最相似的用户的有序列表(从最相似到最不相似)。返回的结果不应包含提供的人员,因为我们知道每个用户都与他们相似。因为这里每个用户的结果都是二进制的,所以(也许)将相似度计算为两个用户的点积是有意义的。

    find_similar_offers('9b98b8c7a33c4b65b9aebfe6a799e6d9')[:5]
    >>> ['3f207df678b143eea3cee63160fa8bed',
     '5a8bc65990b245e5a138643cd4eb9837',
     'ae264e3637204a6fb9bb56bc8210ddfd',
     '4d5c57ea9a6940dd891ad53e9dbe8da0',
     'fafdcd668e3743c1bb461111dcafc2a4']
    

    最后,为了提出推荐使用以下代码:

    offer_offer_recs('3f207df678b143eea3cee63160fa8bed', m=10)
    >>> ['0020ccbbb6d84e358d3414a3ff76cffd',
     '005500a7188546ff8a767329a2f7c76a',
     '0063def0f9c14bc4805322a488839b32',
     '00857b24b13f4fe0ad17b605f00357f5',
     '0092a132ead946ceb30d11a1ed513d20',
     '00ad4c2cace94f67a6354ec90d6c6f45',
     '00b5fb9d842d437e83033ad9e36f7148',
     '00b901d68f8f4fd68075184cd0f772d2',
     '00bbce6533f44ddeaf4dd32bcab55441',
     '00bc983061d3471e8c8e74d31b7c8b6f']
    

    offer_offer_recs将为我们提供 n 个未收到特定优惠的用户。
    我们可以结合基于排名的推荐来改进推荐。
    与其随意选择何时获得与给定报价非常接近的报价,不如先选择人际互动最多的报价,然后再选择人际互动较少的报价。
    与其从推荐人的数量开始低于 m 并结束于 m 的提议中任意选择用户,不如选择总交互次数最多的人,然后选择总交互次数较少的人。

    offer_offer_recs_improved('3f207df678b143eea3cee63160fa8bed')
    >>> ['0020c2b971eb4e9188eac86d93036a77',
     '00426fe3ffde4c6b9cb9ad6d077a13ea',
     '004c5799adbf42868b9cff0396190900',
     '0099bf30e4cb4265875266eb3eb25eab',
     '00b18b535d6d4f779dea4dc9ac451478',
     '00b5fb9d842d437e83033ad9e36f7148',
     '00b901d68f8f4fd68075184cd0f772d2',
     '00bbce6533f44ddeaf4dd32bcab55441',
     '00bc42a62f884b41a13cc595856cf7c3',
     '00c2f812f4604c8893152a5c6572030e']
    

    现在,由于我们已经建立了一个推荐系统,可以为每个提议推荐 n 个人,我们可以结合基于排名的推荐进一步改进它。我们使用了一些过滤来获得前 n 个人的信息报价和 BOGO/折扣报价。

    在get_n_top_non_info_user、 get_n_top_info_user函数中,如果我们设置 topn = 'max' 我们将获得所有可能的用户。

    最后,结合 offer_offer_recs_improved 函数,得到上述函数创建的数据库中的 n 个 top 人物。

    make_recs('4d5c57ea9a6940dd891ad53e9dbe8da0')
    >>> array(['0009655768c64bdeb2e877511632db8f',
           '0011e0d4e6b944f998e987f904e8c1e5',
           '003d66b6608740288d6cc97a6903f4f0',
           '004b041fbfe44859945daa2c7f79ee64',
           '0056df74b63b4298809f0b375a304cf4',
           '0082fd87c18f45f2be70dbcbb0fb8aad',
           '00c6035df45840038a72766c6d27a0db',
           '0009655768c64bdeb2e877511632db8f',
           '0011e0d4e6b944f998e987f904e8c1e5',
           '003d66b6608740288d6cc97a6903f4f0'], dtype=object)
    

    上面的make_recs函数返回前 10 名推荐用户的优惠券:'4d5c57ea9a6940dd891ad53e9dbe8da0'

    1. 如何向新客户推荐优惠券/优惠?
      使用 ML 为新用户提供基于内容的推荐。
      为了训练 ML 模型,我们将使用“transaction_data”。
      给定人口统计信息,我们想要预测值列。
      在此数据中,“人”、“事件”、“时间”和“日期”列不是必需的。
      我们将按“人”对数据进行分组,并尝试预测中值。由于一个人偶尔会花费更多或更少的金额,因此我们通过取中位数来消除这些异常值。
      数据预处理:
      我如何处理 NaN 值?从到目前为止的分析中,我们知道有些行没有人口统计信息。这些行的年龄 = 118,性别 = 未知,收入 = NaN。
      因为我们知道,这些 NaN 值与任何信息无关。因此,我们可以将它们视为异常值,我们可以简单地过滤掉该值并计算平均支出,如果新客户不提供任何人口统计数据,则使用该值。
      看一下数据:
    X_data.head(10) # target variable>>>
       gender       income       age                       
    0       M       72000.0       33                 
    1       O       57000.0       40                 
    2       F       90000.0       59                 
    3       F       60000.0       24                 
    4       F       73000.0       26                 
    5       F       65000.0       19                 
    6       F       74000.0       55                 
    7       M       99000.0       54                 
    8       M       47000.0       56                 
    9       M       91000.0       54
    

    这里的“性别”是一个分类变量,具有 F(女性)、M(男性)、O(其他)类别。“收入”和“年龄”是数字数据。

    图 1. 数值列的分布
    从数值列图中,我们看到“年龄”和“收入”列是右倾斜的。为了使其成为高斯函数,我们将进行对数转换,然后将数据标准化为 0 平均值。
    对于分类列“性别”,我们将使用一次性编码。
    我使用 scikit-learn 管道来执行数据预处理。
    由于我们只有三个特征,我使用了 scikit-learn 中的 PolynomialFeatures 来添加更多特征。可以在此处找到有关其工作原理的详细信息。
    对于目标变量,我将上限值剪裁为 25。因为如果一个人花费超过 25 美元,我们将不会向他们发送任何报价。
    训练 ML 模型
    由于这是一个回归问题,我们可以使用各种回归方法来找到最佳模型。
    我用了:
    线性回归
    随机森林回归
    支持向量机回归器
    XGBoost 回归器
    使用这 4 种方法后,XGBoost 给了我更好的结果,所以我决定将它用作我的最终模型。
    矩阵:
    我们无法计算回归模型的准确性。我们只能根据预测误差来衡量性能。在我们的例子中,我们不想预测确切的美元金额,但我们想看看我们的预测与实际价值有多接近。我将使用 3 个矩阵来评估我的模型。
    R平方:衡量因变量与模型的拟合程度。
    均方根误差 (RMSE):平方误差之和有助于选择最佳回归模型。MSE 对大偏差给予更大的惩罚。
    平均绝对误差 (MAE):类似于 MSE/RMSE,但不是取平方误差,而是计算绝对误差。MAE 对每个错误都一视同仁。

    R_2 分数

    RMSE 分数
    XGBoost 的 R 平方分数为 72–70 %,这意味着该模型非常稳健。
    超参数调优:
    作为最后一步,我们需要调整超参数以获得最佳参数值。
    我使用 scikit-learn 的 RandomizedSearchCV 来找到最佳参数值。
    针对这个问题调整的超参数是:

    模型评估和验证:
    最佳参数是:

    random_cv.best_estimator_
    >>> XGBRegressor(base_score=0.5, booster='gbtree',    colsample_bylevel=1,
                 colsample_bynode=1, colsample_bytree=1, gamma=0, gpu_id=-1,
                 importance_type='gain', interaction_constraints='',
                 learning_rate=0.2, max_delta_step=0, max_depth=3,
                 min_child_weight=3, missing=nan, monotone_constraints='()',
                 n_estimators=100, n_jobs=8, num_parallel_tree=1, random_state=0,
                 reg_alpha=0, reg_lambda=1, scale_pos_weight=1, subsample=1,
                 tree_method='exact', validate_parameters=1, verbosity=None)
    

    图 2. 预测值与实际值的图
    为了评估 XGBoost 模型在所有数据上是否稳定,我们可以使用 K-FOLD CROSS VALIDATION。

    交叉验证
    正如我们所见,该模型在整个数据集上非常稳定,标准差为 0.1。

    最后,我们可以设置向新用户发送优惠券的规则。
    没有人口统计数据的人预计会花费 1.71 美元,因此我们可以发送信息报价或不报价!
    如果用户预计花费 < 3 美元或 >22 美元,请发送信息报价或无报价!
    如果用户预计花费 ≥ 3 美元且 < 5 美元,则发送 5美元优惠券。
    如果用户预计花费 ≥ 5 美元且 < 7 美元,则发送 7美元优惠券。
    如果用户预计花费 ≥ 7 美元且 < 10 美元,则发送 10美元的优惠券。
    最后,如果用户预计花费 ≥ 10 美元且 < 20 美元,则发送 20美元优惠券。
    例子:

    person_demo = {
        'gender' : ['M','F','O'],
        'income' : [60000.0,72000.0,80000.0],
        'age' : [36,26,30]
    }predict_expense(person_demo, final_model)>>> array([ 3.78, 10.66, 22.26], dtype=float32)
    

    第 1 个人:性别 = 男,收入 = 60000.00,年龄 = 36。预计花费 3.78 美元,因此送出5 美元的优惠券。
    第 2 个人:性别 = 女性,收入 = 72000.00,年龄 = 26。预计花费 10.66 美元,因此送出20 美元的优惠券。
    第 3 个人:性别 = 其他,收入 = 80000.00,年龄 = 30。预计花费 22.26 美元,因此发送信息优惠券/根本没有优惠券!

    概括
    总之,我创建了一个基于排名的推荐系统,以过滤掉最有可能查看和兑换现有或未来优惠的潜在用户。我使用了一种基于用户用户的协同过滤方法来找出特定于某个优惠的顶级潜在用户。
    最后,我使用机器学习方法 向新用户推荐优惠。

    项目理由
    我试图通过这个项目回答 3 个问题。
    对于问题 1.有哪些受欢迎的优惠类型?
    从第 1 部分的情节中,可能的答案是,
    我绘制了收到的报价与报价类型的百分比图来显示,即使 BOGO 报价被查看更多,折扣报价在完成方面更受欢迎。

    我创建了一个性别之间的报价分布图来得出结论,给出一个报价,兑换报价的机会在女性和其他性别中更高!

    最后,我绘制了性别、年龄、收入与平均支出的关系图,发现女性往往支出最多,而且支出随着年龄和收入的增加而增加。

    对于问题 2.如何根据现有客户的消费模式向他们推荐优惠券/优惠?
    我使用基于排名的推荐系统来过滤掉最有可能查看和兑换现有或未来优惠的潜在用户。
    我创建了一种基于用户用户的协同过滤方法,以找出特定于某项优惠的顶级潜在用户。

    对于问题 3,如何向新客户推荐优惠券/优惠?
    我使用了各种矩阵(MAE/RMSE)来验证模型的稳健性。我发现 RMSE 约为 4.5。虽然,仅区分 5 美元和 7 美元的报价或 7 美元的报价和 10 美元的报价是不够的,但只有一个 7 美元的报价、两个 5 美元的报价和四个 10 美元的报价。因此,将 5 美元的报价与 10 美元的报价区分开来更为重要。为此,RMSE 分数就足够了。

    此方法可用于向新用户推荐优惠。

    未来的工作
    将来,计划在网络上部署模型并构建数据仪表板。
    我将尝试通过执行更多的特征工程来提高模型性能。合成少数过采样技术 (SMOT) 以增加训练数据。
    使用 CatBoost 和 LightGBM 模型来尝试检查结果。
    使用堆叠,因为使用了多个监督学习模型。
    这个项目的 GitHub 存储库可以在这里找到。

    相关文章

      网友评论

          本文标题:Pandas和NumPy(第二部分)

          本文链接:https://www.haomeiwen.com/subject/ezgrsrtx.html