机器学习案例8:基于随机森林的otto产品预测

案例8:基于随机森林的otto产品预测

为什么写本博客

​ 前人种树,后人乘凉。希望自己的学习笔记可以帮助到需要的人。

需要的基础

​ 懂不懂原理不重要,本系列的目标是使用python实现机器学习。

​ 必须会的东西:python基础、numpy、pandas、matplotlib和库的使用技巧。

说明

​ 完整的代码在最后,另外之前案例中出现过的方法不会再讲解。

目录结构

1. 涉及的新方法:

RF模型

from sklearn.ensemble import RandomForestClassifier
# 创建模型
model = RandomForestClassifier()
'''
主要参数:
	n_estimators : 指定森林里面树木数量
	max_depth : 树的最大深度
	min_samples_leaf : 叶子节点最小样本数
	oob_score:使用没有被选中的数据集来进行自我验证
'''

随机欠采样

注意这里需要重新安装模块imblearn。

from imblearn.under_sampling import RandomUnderSampler
# 创建对象:设置随机数种子可以使得实验可以重复
rus = RandomUnderSampler(random_state=0)
# 欠采样
X_resampled, y_resampled = rus.fit_resample(x, y)

标签值转为数字值

from sklearn.preprocessing import LabelEncoder
# 创建对象
le = LabelEncoder()
# 转换
y = le.fit_transform(label)

one-hot编码

from sklearn.preprocessing import OneHotEncoder
# 创建对象
one_hot = OneHotEncoder(sparse=False)
# 参数: sparse=False,直接返回array对象,否则还需要转为array对象
# 转换
y_test = one_hot.fit_transform(y_test)

logloss

# 多分类评估
from sklearn.metrics import log_loss
loss = log_loss(y_test, y_pre)

2. 数据集获取与介绍:

数据下载

​ 本次的案例数据来自于kaggle比赛里面的数据,链接为: https://www.kaggle.com/competitions/otto-group-product-classification-challenge/data,可以下载相关数据集,也可以通过百度网盘获取:

链接:https://pan.baidu.com/s/1oVz8qyMajmWu53GAPnP_IQ 
提取码:6666 

数据介绍

​ 奥托集团是世界上最⼤的电⼦商务公司之⼀。案例要求对奥拓集团的产品进⾏正确的分类。

数据总共有2000000种产品(总共的,训练集有61878条),共93个特征,9个类别

id feat_1 .... feat_93 target
产品id 93个特征 产品类别

3. 数据加载与欠采样处理:

数据加载

​ 常规的加载csv数据,利用pandas库:

# 加载数据
train_data = pd.read_csv('./data/otto/train.csv')
print(train_data.head())
print(train_data.shape) # (61878, 95)

数据查看

​ 我们可以使用matplotlib画一个条形图看看不同类别的数据量多少:

# 查看数据
plt.figure()
x = ['Class_1','Class_2','Class_3','Class_4','Class_5','Class_6','Class_7','Class_8','Class_9']
y = [(train_data.target == i).sum() for i in x] # 查找不同类别的个数
plt.bar(x,y)
plt.show()

​ 画出的图为:

在这里插入图片描述

从这里可以看出,数据分布不均衡,这会对我们的模型造成很大的影响。

随机欠采样

​ 处理类别不平衡的方法,这里采取随机欠采样,原理十分简单,就是对于多类别的样本随机抛去一些,使得所有类别样本量大致相同。

​ 首先,把训练集的x和y提取出来:

y = train_data['target']
x = train_data.iloc[:,1:-1] # 除去id和target列的,所有列
print(x.shape) # (61878, 93)
print(y.shape) # (61878,)

​ 然后根据随机欠采样的方法使用即可:

# 随机欠采样
rus = RandomUnderSampler(random_state=20)
new_x,new_y = rus.fit_resample(x,y)
print(new_x.shape) # (17361, 93)
print(new_y.shape) #  (17361,)

​ 再次查看数据图:

# 查看数据图2
plt.figure()
x = ['Class_1','Class_2','Class_3','Class_4','Class_5','Class_6','Class_7','Class_8','Class_9']
y = [(new_y == i).sum() for i in x]
plt.bar(x,y)
plt.show()

​ 结果如下图:

在这里插入图片描述

4. 标签值转为数字值:

​ 首先,我们将数据的label由字符串转为数字0-8,可以手动转换,也可以使用自带的方法:

# 标签 -- 数字
encoder = LabelEncoder()
new_y = encoder.fit_transform(new_y)
print(new_y)

​ 打印结果为:

[0 0 0 ... 8 8 8]

​ 另外,由于数据本身比较大,我们可以在此基础上划分为训练集和测试集(当然,kaggle本身提供了测试集

# 数据划分
x_train,x_test,y_train,y_test = train_test_split(new_x,new_y,test_size=0.2)

5. 模型创建、训练:

​ 下面,进行模型的创建和训练:

# 创建模型
model = RandomForestClassifier(oob_score=True)
model.fit(x_train, y_train)

6. 评估:

​ 这里我们使用**logloss(多分类对数损失)**进行评估,其公式为:

在这里插入图片描述

但是这里注意:logloss要求y必须为one-hot编码形式,因此需要做出一定的转换。

​ 首先,得到预测值:

y_pred = model.predict(x_test)

​ 然后,one-hot编码:

# one-hot
encoder_oneHot = OneHotEncoder(sparse=False)
y_test = encoder_oneHot.fit_transform(y_test.reshape(-1,1)) # 需要转为矩阵
y_pred = encoder_oneHot.fit_transform(y_pred.reshape(-1,1))

​ 进行评估:

# logloss
print('log_loss:',log_loss(y_test,y_pred))

​ 打印结果为:

log_loss: 7.677493629965759

7. 总结:

​ 上面仅仅是初步实现了整体算法流程,但是关于如何提高准确率,如何选定参数并没有讨论,但是肯定也没有什么好的方法,只能大致迭代尝试。

​ 另外,这里也给我了一个提醒,在前面实现决策树算法的时候,是不是因为对于数据没有处理好,导致结果并不理想,后面有机会尝试修改一下。

完整代码

# author: baiCai
# 导包
import pandas as pd
import numpy as np
import seaborn
from matplotlib import pyplot as plt
from imblearn.under_sampling import RandomUnderSampler
from sklearn.preprocessing import LabelEncoder,OneHotEncoder
from sklearn.model_selection import train_test_split
from sklearn.metrics import log_loss
from sklearn.ensemble import RandomForestClassifier

# 加载数据
train_data = pd.read_csv('./data/otto/train.csv')
# print(train_data.head())
# print(train_data.shape) # (61878, 95)
'''
# 查看数据图1
plt.figure()
x = ['Class_1','Class_2','Class_3','Class_4','Class_5','Class_6','Class_7','Class_8','Class_9']
y = [(train_data.target == i).sum() for i in x]
plt.bar(x,y)
plt.show()
'''
y = train_data['target']
x = train_data.iloc[:,1:-1]
# print(x.shape) # (61878, 93)
# print(y.shape) # (61878,)
# 随机欠采样
rus = RandomUnderSampler(random_state=20)
new_x,new_y = rus.fit_resample(x,y)
# print(new_x.shape) # (17361, 93)
# print(new_y.shape) #  (17361,)
'''
# 查看数据图2
plt.figure()
x = ['Class_1','Class_2','Class_3','Class_4','Class_5','Class_6','Class_7','Class_8','Class_9']
y = [(new_y == i).sum() for i in x]
plt.bar(x,y)
plt.show()
'''
# 标签 -- 数字
encoder = LabelEncoder()
new_y = encoder.fit_transform(new_y)
# print(new_y)
# 数据划分
x_train,x_test,y_train,y_test = train_test_split(new_x,new_y,test_size=0.2)
# 创建模型
model = RandomForestClassifier(n_estimators=175,max_features=15,max_depth=30,min_samples_leaf=1,oob_score=True)
model.fit(x_train, y_train)
# 评估1
print('准确率:',model.score(x_test,y_test))
# 评估2
y_pred = model.predict(x_test)
# one-hot
encoder_oneHot = OneHotEncoder(sparse=False)
y_test = encoder_oneHot.fit_transform(y_test.reshape(-1,1)) # 需要转为矩阵
y_pred = encoder_oneHot.fit_transform(y_pred.reshape(-1,1))
# logloss
print('log_loss:',log_loss(y_test,y_pred))
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值