前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >kaggle实战-揭秘黑色星期五

kaggle实战-揭秘黑色星期五

作者头像
皮大大
发布2023-08-25 10:50:37
3610
发布2023-08-25 10:50:37
举报
文章被收录于专栏:机器学习/数据可视化

揭秘黑色星期五:深度学习略胜随机森林

本文是kaggle的一个新案例,使用是一份关于国外黑色星期五的消费数据。

西方国家的黑色星期五类似我国的“双十一”活动,会产生很多的消费数据。

本数据提供了黑色星期五当天用户精选大批量产品产生的购买信息,主要包含两部分:

  • 客户人口统计信息(年龄,性别,婚姻状况,城市类别,定居时长)
  • 商品详细信息(商品id和商品类别)以及总购买金额

导入库

代码语言:javascript
复制
import pandas as pd
import numpy as np

import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.patches as mpatches
import matplotlib
# 中文显示问题
plt.rcParams["font.sans-serif"]=["SimHei"] #设置字体
plt.rcParams["axes.unicode_minus"]=False #正常显示负号

import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
from plotly.offline import init_notebook_mode, iplot

plt.style.use('ggplot')
sns.set(context='notebook',
        style='darkgrid',
        palette='colorblind',
        font='sans-serif',
        font_scale=1,
        rc=None)

matplotlib.rcParams['figure.figsize'] =[8,8]
matplotlib.rcParams.update({'font.size': 15})
matplotlib.rcParams['font.family'] = 'sans-serif'

from sklearn.impute import KNNImputer
from sklearn.model_selection import train_test_split

# 忽略notebook中的警告
import warnings
warnings.filterwarnings("ignore")

数据基本信息

代码语言:javascript
复制
df1 = pd.read_csv("train.csv")
df1.head()

数据基本信息:

In [3]:

代码语言:javascript
复制
df1.shape

Out[3]:

总共是55万+的数据:

代码语言:javascript
复制
(550068, 12)

In [4]:

代码语言:javascript
复制
columns = df1.columns  # 全部的字段
columns

Out[4]:

代码语言:javascript
复制
Index(['User_ID', 'Product_ID', 'Gender', 'Age', 'Occupation', 'City_Category',
       'Stay_In_Current_City_Years', 'Marital_Status', 'Product_Category_1',
       'Product_Category_2', 'Product_Category_3', 'Purchase'],
      dtype='object')

In [5]:

代码语言:javascript
复制
df1.dtypes

Out[5]:

代码语言:javascript
复制
User_ID                         int64
Product_ID                     object
Gender                         object
Age                            object
Occupation                      int64
City_Category                  object
Stay_In_Current_City_Years     object
Marital_Status                  int64
Product_Category_1              int64
Product_Category_2            float64
Product_Category_3            float64
Purchase                        int64
dtype: object

In [6]:

代码语言:javascript
复制
# 不同字段类型的占比

df1.dtypes.value_counts().plot.pie(explode=[0.1,0.1,0.1],
                                   autopct='%1.2f%%',
                                   shadow=True)
plt.title('type of our data')

plt.show()

字段基本信息

缺失值情况

查看整体数据的缺失值情况,后面会专门处理缺失值:

统计与可视化分析

从不同的角度对数据进行数量统计和可视化的分析

性别分析

In [9]:

代码语言:javascript
复制
df2 = df1["Gender"].value_counts().reset_index()
df2

Out[9]:

index

Gender

0

M

414259

1

F

135809

In [10]:

不同性别下的数量分布统计:

代码语言:javascript
复制
colors = ["red", "blue"]

sns.countplot("Gender", data=df1, palette=colors)
plt.title("Gender Count")
plt.show()

不同性别下的数量占比统计:

代码语言:javascript
复制
# 统计不同性别的个数
size = df1['Gender'].value_counts()

labels = ['Male', 'Female']
colors = ['#C4061D', 'green']
explode = [0, 0.1]

plt.rcParams['figure.figsize'] = (10, 10)
plt.pie(size,
        colors = colors,
        labels = labels,
        shadow = True,
        explode = explode,
        autopct = '%.2f%%')

plt.title('Gender Percent', fontsize = 20)
plt.axis('off')
plt.legend()
plt.show()

职位分析

In [12]:

代码语言:javascript
复制
df3 = df1["Occupation"].value_counts().sort_index().reset_index()
df3.head()

Out[12]:

index

Occupation

0

0

69638

1

1

47426

2

2

26588

3

3

17650

4

4

72308

In [13]:

代码语言:javascript
复制
fig = px.bar(df3,
						"index",
						"Occupation",
						color="Occupation")
fig.show()

不同职位下的数量统计:可以看到0-4-7的职位消费人数是最多的

下面是基于seaborn的统计方法:

代码语言:javascript
复制
palette=sns.color_palette("Set2")

plt.rcParams['figure.figsize'] = (18, 9)
sns.countplot(df1['Occupation'], palette = palette)

plt.title('total number of Occupation',   # 消费人次
          fontsize = 20)

plt.xlabel('Occupation')
plt.ylabel('number')
plt.show()

每个职位的总消费

不同职位下的消费总金额:

In [69]:

代码语言:javascript
复制
sum_by_occ = df1.groupby('Occupation')['Purchase'].sum()
plt.figure(figsize=(20, 6))

sns.barplot(x=sum_by_occ.index,y=sum_by_occ.values)
plt.title('total amount of Occupation')
plt.show()

年龄段

In [16]:

代码语言:javascript
复制
df4 = df1["Age"].value_counts().reset_index().sort_values("index")
df4

Out[16]:

index

Age

6

0-17

15102

2

18-25

99660

0

26-35

219587

1

36-45

110013

3

46-50

45701

4

51-55

38501

5

55+

21504

In [17]:

代码语言:javascript
复制
fig = px.pie(df4, names="index",values="Age")

fig.update_traces(textposition='inside', textinfo='percent+label')

fig.show()

柱状图的表示方法:

性别+年龄段

In [19]:

代码语言:javascript
复制
columns

Out[19]:

代码语言:javascript
复制
Index(['User_ID', 'Product_ID', 'Gender', 'Age', 'Occupation', 'City_Category',
       'Stay_In_Current_City_Years', 'Marital_Status', 'Product_Category_1',
       'Product_Category_2', 'Product_Category_3', 'Purchase'],
      dtype='object')

In [20]:

代码语言:javascript
复制
df5 = df1.groupby(["Gender", "Age"]).size().reset_index()
df5.columns = ["Gender" ,"Age", "Number"]

df5

Out[20]:

Gender

Age

Number

0

F

0-17

5083

1

F

18-25

24628

2

F

26-35

50752

3

F

36-45

27170

4

F

46-50

13199

5

F

51-55

9894

6

F

55+

5083

7

M

0-17

10019

8

M

18-25

75032

9

M

26-35

168835

10

M

36-45

82843

11

M

46-50

32502

12

M

51-55

28607

13

M

55+

16421

In [21]:

代码语言:javascript
复制
fig = px.bar(df5, x="Age", y="Number", color="Gender", text="Number")

fig.show()

城市属性分析

In [72]:

代码语言:javascript
复制
plt.rcParams['figure.figsize'] = (18, 9)
# 统计每个城市的数量
sns.countplot(df1['City_Category'], palette = palette)

plt.title('people of city', fontsize = 20)
plt.xlabel('city')
plt.ylabel('people')
plt.show()

停留年限df6-Stay_In_Current_City_Years

下面是对停留年限字段的统计分析:

In [23]:

代码语言:javascript
复制
df6 = df1["Stay_In_Current_City_Years"].value_counts().reset_index()
df6

Out[23]:

index

Stay_In_Current_City_Years

0

1

193821

1

2

101838

2

3

95285

3

4+

84726

4

0

74398

In [24]:

代码语言:javascript
复制
fig = px.pie(df6, names="index",values="Stay_In_Current_City_Years")

fig.update_traces(textposition='inside', textinfo='percent+label')

fig.show()

婚姻状态Marital_Status

0-未婚 1-已婚

In [25]:

代码语言:javascript
复制
df1["Marital_Status"].value_counts(normalize=True)

Out[25]:

代码语言:javascript
复制
0    0.590347
1    0.409653
Name: Marital_Status, dtype: float64

Product_Category_1

In [26]:

代码语言:javascript
复制
df8 = df1["Product_Category_1"].value_counts(normalize=True).reset_index()
df8.head()

Out[26]:

index

Product_Category_1

0

5

0.274390

1

1

0.255201

2

8

0.207111

3

11

0.044153

4

2

0.043384

In [27]:

下面的图形显示的是Product_Category_1字段中每个取值的占比,主要集中在1-5-8

代码语言:javascript
复制
fig = px.bar(df8, x="index",y="Product_Category_1")
fig.show()

查看字段Product_Category_1的相关统计信息:

同样的方法可以查看Product_Category_2和Product_Category_3的相关分布和统计信息。

缺失值处理

查看缺失值

In [29]:

代码语言:javascript
复制
df1.isnull().sum()  # 查看缺失值情况

Out[29]:

代码语言:javascript
复制
User_ID                            0
Product_ID                         0
Gender                             0
Age                                0
Occupation                         0
City_Category                      0
Stay_In_Current_City_Years         0
Marital_Status                     0
Product_Category_1                 0
Product_Category_2            173638
Product_Category_3            383247
Purchase                           0
dtype: int64

缺失值处理

缺失值的处理方式:

  1. 删除缺失值的数据
  2. 填充缺失值:用0填充、均值或其他统计值填充、前向或后向的值填充、KNN算法的差值填充

方法1:均值填充

In [30]:

代码语言:javascript
复制
# 针对Product_Category_2

median = df1["Product_Category_2"].median()
median

Out[30]:

代码语言:javascript
复制
9.0

In [31]:

代码语言:javascript
复制
df1["Product_Category_2"].fillna(median, inplace=True)  # 填充均值

assert断言是否有缺失值:

In [32]:

代码语言:javascript
复制
df1.isnull().sum()

Out[32]:

代码语言:javascript
复制
User_ID                            0
Product_ID                         0
Gender                             0
Age                                0
Occupation                         0
City_Category                      0
Stay_In_Current_City_Years         0
Marital_Status                     0
Product_Category_1                 0
Product_Category_2                 0  # 没有缺失值
Product_Category_3            383247
Purchase                           0
dtype: int64

方法2:前后项填充

In [33]:

代码语言:javascript
复制
# 查看缺失值所在的行
df1[df1.isnull().T.any()]

我们发现Product_Category_3字段在首尾都存在缺失值,因此我们使用前后项同时填充的方法:

目标变量正态化

将目标变量Purchase进行正态化

In [38]:

代码语言:javascript
复制
from scipy import stats
from scipy.stats import norm

In [39]:

代码语言:javascript
复制
plt.rcParams['figure.figsize'] = (20, 7)
sns.distplot(df1['Purchase'], # 实施变换的值
             color = 'green',  # 颜色
             fit = norm  # 拟合正态化
            )

# 均值和标准差
mu, sigma = norm.fit(df1['Purchase'])
print("The mu {} and Sigma {} for the curve".format(mu, sigma))

plt.title('目标变量分布')
plt.legend(['正态分布($mu$: {}, $sigma$: {}'.format(mu, sigma)], loc = 'best')
plt.show()

字段处理

删除无效字段

In [40]:

代码语言:javascript
复制
df1.drop(["User_ID", "Product_ID"], inplace=True, axis=1)

In [41]:

代码语言:javascript
复制
df1.columns

Out[41]:

代码语言:javascript
复制
Index(['Gender', 'Age', 'Occupation', 'City_Category',
       'Stay_In_Current_City_Years', 'Marital_Status', 'Product_Category_1',
       'Product_Category_2', 'Product_Category_3', 'Purchase'],
      dtype='object')

字符型字段

In [42]:

代码语言:javascript
复制
df9 = df1.select_dtypes(include="object")
cat_col = df9.columns
cat_col

Out[42]:

代码语言:javascript
复制
Index(['Gender', 'Age', 'City_Category', 'Stay_In_Current_City_Years'], dtype='object')

In [43]:

代码语言:javascript
复制
df10 = df1.select_dtypes(exclude="object")  # 数值型变量

特征工程

哑变量

对字符型字段进行独热码,生成哑变量

In [44]:

代码语言:javascript
复制
df_Gender = pd.get_dummies(df1['Gender'])
df_Age = pd.get_dummies(df1['Age'])
df_City_Category = pd.get_dummies(df1['City_Category'])
df_Stay_In_Current_City_Years = pd.get_dummies(df1['Stay_In_Current_City_Years'])

合并

In [45]:

代码语言:javascript
复制
df11 = pd.concat([df10, df_Gender, df_Age, df_City_Category, df_Stay_In_Current_City_Years], axis=1)

标准化

In [46]:

代码语言:javascript
复制
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler

In [47]:

代码语言:javascript
复制
X = df11.drop("Purchase", axis=1)
y = df11["Purchase"]

In [48]:

代码语言:javascript
复制
columns = X.columns

In [49]:

代码语言:javascript
复制
ss = StandardScaler()
X = ss.fit_transform(X)
# 数据还原
# origin_data = ss.inverse_transform(ss_X)
X = pd.DataFrame(X, columns=columns)
X

Out[49]:

数据分割

In [50]:

代码语言:javascript
复制
# 切分比例为8:2
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=10)

X_train.shape

Out[50]:

代码语言:javascript
复制
(440054, 22)

线性回归

建模

In [51]:

代码语言:javascript
复制
from sklearn.linear_model import LinearRegression

lr = LinearRegression()
lr.fit(X_train, y_train)

Out[51]:

代码语言:javascript
复制
LinearRegression()

In [52]:

代码语言:javascript
复制
LinearRegression(copy_X=True,
                 fit_intercept=True,
                 n_jobs=None,
                 normalize=False)

Out[52]:

代码语言:javascript
复制
LinearRegression(normalize=False)

In [53]:

代码语言:javascript
复制
print('Intercept parameter:', lr.intercept_)

coeff_df = pd.DataFrame(lr.coef_,
                        X.columns,
                        columns=['Coefficient'])
coeff_df
Intercept parameter: 9262.589703346423

预测

对测试集的预测

In [54]:

代码语言:javascript
复制
predictions = lr.predict(X_test)
predictions

Out[54]:

代码语言:javascript
复制
array([ 7982.58970335,  9525.58970335,  7910.58970335, ...,
       12058.58970335,  9946.58970335,  8621.83970335])

评价指标

In [55]:

代码语言:javascript
复制
from sklearn import metrics

# 回归问题的两个重要指标
print('MAE:', metrics.mean_absolute_error(y_test, predictions))
print('MSE:', metrics.mean_squared_error(y_test, predictions))
MAE: 3591.343500225385
MSE: 21934597.75355938

随机森林回归

建模

随机森林中3个重要的属性:

  • 查看森林中树的状况:estimators_
  • 袋外估计准确率得分:oob_score_,必须是oob_score参数选择True的时候才可用
  • 变量的重要性:feature_importances_

In [56]:

代码语言:javascript
复制
from sklearn.ensemble import RandomForestRegressor

rf = RandomForestRegressor(max_depth=5)

rf.fit(X_train, y_train)

Out[56]:

代码语言:javascript
复制
RandomForestRegressor(max_depth=5)

预测

In [57]:

代码语言:javascript
复制
predictions_rf = rf.predict(X_test)
predictions_rf

Out[57]:

代码语言:javascript
复制
array([ 7895.32997516,  6153.32785418,  7895.32997516, ...,
       15413.87676836,  2229.59133606,  6153.32785418])

评价指标

In [58]:

代码语言:javascript
复制
from sklearn import metrics

# 回归问题的两个重要指标
print('MAE:', metrics.mean_absolute_error(y_test, predictions_rf))
print('MSE:', metrics.mean_squared_error(y_test, predictions_rf))
MAE: 2396.6110975637253
MSE: 10568250.95352542

基于keras神经网络

数据缩放

神经网络中输入的数据一般都是比较小的,我们将输出y_train和y_test缩小10000倍,即以万为单位:

In [59]:

代码语言:javascript
复制
import tensorflow as tf
from keras import models
from keras import layers

np.random.seed(123)

pd.options.mode.chained_assignment = None

In [60]:

代码语言:javascript
复制
y_train /= 10000
y_test /= 10000

构建网络

In [61]:

代码语言:javascript
复制
model = models.Sequential()
model.add(tf.keras.layers.Dense(64,
                                activation="relu",
                                input_shape=(X_train.shape[1],)))

model.add(tf.keras.layers.Dense(64,
                                activation="relu"))

model.add(tf.keras.layers.Dense(1))

编译网络

In [62]:

代码语言:javascript
复制
model.compile(optimizer="rmsprop",  # 优化器
              loss="mse",  # 损失函数
              metrics=["mae"]  # 评估指标:平均绝对误差
             )

训练网络

In [63]:

代码语言:javascript
复制
history = model.fit(X_train,
                    y_train,
                    epochs=100,
                    validation_split=0.2,
                    batch_size=4500,
                    verbose=0  # 0-静默模式 1-日志模式
                   )

指标可视化

In [64]:

代码语言:javascript
复制
mae_history = history.history["mae"]
loss_history = history.history["loss"]

In [65]:

代码语言:javascript
复制
len(mae_history)

Out[65]:

代码语言:javascript
复制
100

In [66]:

代码语言:javascript
复制
# 损失绘图
import matplotlib.pyplot as plt

epochs = range(1,len(loss_history) + 1)

plt.plot(epochs,  # 循环轮数
         loss_history,  # loss取值
         "r",
         label="loss"
        )

plt.plot(epochs,
         mae_history,
         "b",
         label="mae"
        )

plt.title("Loss and Mae")
plt.xlabel("Epochs")
plt.legend()

plt.show()

模型预测

In [67]:

代码语言:javascript
复制
model.evaluate(X_test, y_test)
3438/3438 [==============================] - 7s 2ms/step - loss: 0.0975 - mae: 0.2382

Out[67]:

代码语言:javascript
复制
[0.09745179861783981, 0.2381529062986374]

对比

3种方案的对比(深度学习的指标中得到的结果需要进行转化还原)

LOSS(MSE)

MAE

线性回归

21,934,597

3591

随机森林回归

10,568,250

2396

深度学习Keras

0.09745(9,745,000)

0.2381(2381)

所以来说:深度学习还是略胜一筹!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-5-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 揭秘黑色星期五:深度学习略胜随机森林
  • 导入库
  • 数据基本信息
    • 字段基本信息
    • 缺失值情况
    • 统计与可视化分析
      • 性别分析
        • 职位分析
          • 每个职位的总消费
            • 年龄段
              • 性别+年龄段
                • 城市属性分析
                  • 停留年限df6-Stay_In_Current_City_Years
                    • 婚姻状态Marital_Status
                      • Product_Category_1
                      • 缺失值处理
                        • 查看缺失值
                          • 缺失值处理
                            • 方法1:均值填充
                              • 方法2:前后项填充
                              • 目标变量正态化
                              • 字段处理
                                • 删除无效字段
                                  • 字符型字段
                                  • 特征工程
                                    • 哑变量
                                      • 合并
                                        • 标准化
                                          • 数据分割
                                          • 线性回归
                                            • 建模
                                              • 预测
                                                • 评价指标
                                                • 随机森林回归
                                                  • 建模
                                                    • 预测
                                                      • 评价指标
                                                      • 基于keras神经网络
                                                        • 数据缩放
                                                          • 构建网络
                                                            • 编译网络
                                                              • 训练网络
                                                                • 指标可视化
                                                                  • 模型预测
                                                                  • 对比
                                                                  领券
                                                                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档