scikit-learn实现ebay数据分析

栏目: 数据库 · 发布时间: 5年前

内容简介:数据中的特征名及其对应描述:

ebay在线拍卖数据

ebay在线拍卖数据 的数据集下载地址为 Ebay Data Set

raw.tar.gz 中包括 TrainingSet.csvTestSet.csvTrainingSubset.csvTestSubset.csv 四个数据文件,下表列出了这四个文件的内容简介

数据名 数据描述
TrainingSet 2013年4月的所有拍卖
TestSet 2013年5月第一个周的所有拍卖
TrainingSubset 2013年4月成功交易的所有拍卖
TestSubset 2013年5月第一周成功交易的所有拍卖

数据中的特征名及其对应描述:

特征名 特征描述
Prices 最终交易金额
StartingBid 拍卖的最低交易金额
BidCount 此项拍卖获得的投标数
Title 交易标题
QuantitySold 成功销售的数量(0或1表示)
SellerRating 卖家在ebay上的评级
StartDate 拍卖开始的日期
EndDate 拍卖结束的日期
PositiveFeedbackPercent 卖家收到的正反馈百分比(占所有反馈)
HasPicture 是否有实物图(0或1)
MemberSince 卖家创建其在ebay上的账户日期
HasStore 卖家是否有ebay店铺(0或1)
SellerCountry 卖家所在的国家
BuyitNowPrice 立即购买该商品的价格
HighBidderFeedbackRating 出价最高的投标者的ebay评级
ReturnsAccepted 是否接受退货(0或1表示)
HasFreeShipping 是否包邮(0或1表示)
IsHOF 卖家中是否是名人堂中的玩家(0或1表示)
IsAuthenticated 是否受到工会的认证(0或1表示)
HasInscription 拍卖项目是否有登记过(0或1表示)
AvgPrice 库存中关于这款商品的平均价格
MedianPrice 库存中这款商品价格的中位数
AuctionCount 库存中拍卖的总数
SellerSaleToAveragePriceRatio 这项拍卖商品的价格占平均价格的比例
StateDayOfWeek 拍卖开始时是周几
EndDayOfWeek 拍卖结束时是周几
AuctionDuration 拍卖持续的天数
StartingBidPercent 该商品投标底线占平均交易价格的比例
SellerClosePercent 一个卖家成功交易的拍卖数占所有在线拍卖数的比例
ItemAuctionSellPercent 成功交易的拍卖数占所有在线拍卖数的比例

数据导入及可视化

实验用的环境是Jupyter Python3.6

首先导入相关的包:

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline

读入数据:

test_set = pd.read_csv("Data/TestSet.csv")
train_set = pd.read_csv("Data/TrainingSet.csv")
test_subset = pd.read_csv("Data/TestSubset.csv")
train_subset = pd.read_csv("Data/TrainingSubset.csv")

输出查看train_set的数据:

train_set.info() # Output train_set data

也可以使用 head() 查看前5条数据

train_set.head()

scikit-learn实现ebay数据分析 第一列属性 EbayID 为每条拍卖纪录的ID号,与预测拍卖是否成功没有联系,因此在模型训练时应该将该特征去除。 QuantitySold 属性为1代表拍卖成功,为0代表拍卖失败,其中 SellerName 拍卖卖方的名字与预测拍卖是否成功也没有关系,因此在训练时也应将该特征去除

train_data = train_set.drop(['EbayID','QuantitySold','SellerName'],axis = 1)
train_target = train_set['QuantitySold']
# Gets the total number of features
n_trainSamples, n_features = train_data.shape

这里再解释一下,为什么要删除 QuantitySold 这个特征。因为我们要将样本数据分成两部分,一是纯的特征数据,二是对应的标签,上面的 train_data 就是特征数据, train_target 就是特征标签(是否成功拍卖)

可视化数据,取出一部分数据,两两组成对看数据在这个2维平面上的分布情况

# isSold: Auction success is 1, auction failure is 0
df = pd.DataFrame(np.column_stack((train_data, train_target)), columns = list(range(n_features)) + ['isSold'])
sns.pairplot(df[:50], vars = [2,3,4,10,13], hue = 'isSold', size = 1.5)

numpy 中矩阵列合并有两个函数,一是 hstack() ,另一个是这里用到的 column_stack ,这两者的区别在于:如果合并的矩阵中有某一个矩阵是稀疏矩阵(有很多0),则最好用 column_stack

scikit-learn实现ebay数据分析 从第 3,9,12,16 维特征的散列图及柱状图可看出,这几个维度并没有很好的区分度,横纵坐标的值分别代表不同维度之间的负相关性,为了查看数据特征之间的相关性,及不同特征与类别 isSold 之间的关系,我们可以利用 seaborn 中的热度图来显示其俩俩组队之间的 相关性

train = train_set.drop(['EbayID','SellerName'],axis = 1)
plt.figure(figsize = (10,10))

# The correlation matrix of the data is calculated
corr = train.corr()

# produce keep out the heat map triangle part of the mask, because the heat the graph is symmetric matrix
# so you just output the lower triangular part
mask = np.zeros_like(corr, dtype = np.bool)
mask[np.triu_indices_from(mask)] = True

# Produces the corresponding color change in the heat map
cmap = sns.diverging_palette(220, 10, as_cmap = True)

# Call the heat in seanborn to create a heat map
sns.heatmap(corr, cmap = cmap, mask = mask, vmax = .3,
            square = True, xticklabels = 5, yticklabels = 2,
            linewidths = .5, cbar_kws = {'shrink':.5})

# Rotate yticks into the horizontal direction for easy viewing
plt.yticks(rotation = 0)

plt.show()

![]()

颜色越偏红,相关性越大,越偏蓝相关性越小且负相关,白色即两个特征之间没有多大的关联,通过第一列可看出,不同维的属性与类别isSold之间的关系,其中第 3,9,12,16 维特征与拍卖是否会成功有很强的 正相关性 ,其中 3,9,12,16 分别对应属性 SellerClosePercentHitCountSellerSaleAvgPriceRatioBestOffer ,表示当这些属性的值越大时越有可能拍卖成功,其中第6维特征 StartingBid 与成功拍卖 isSold 之间呈现较大的负相关性,可看出当拍卖投标的底价越高,则这项拍卖的成功性就越低

通过这副热度图的第二列我们还可以看出不同特征与价格Price之间的相关性

利用数据预测拍卖是否会成功

由于数据量比较大,且特征维度也不是特别少,因此一开始做 baseline 时,就不利用 SVM支持向量机 这些较简单的模型,因为当数据量比较大,且维度较高时,有些简单的机器学习算法并不高效,且可能训练到最后都不收敛

根据 scikit-learn 提供的 机器学习算法使用图谱
scikit-learn实现ebay数据分析

scikit-learn官方介绍(国内进不去)

图谱推荐先使用 SGDClassifier ,其全称为 Stochastic Gradient Descent 随机梯度下降 ,通过 梯度下降法 在训练过程中没有用到所有的训练样本,而是随机从训练样本中选取一部分进行训练,但是 SGD 对特征值的大小比较敏感,而通过上面的数据站视,可以知道在我们的数据集里有数值较大的数据,如 Category 。因此我们需要先使用 sklearn.preprocessing 提供的 StandardScaler 对数据进行预处理,使其每个属性的波动幅度不要太大,有助于训练时函数收敛

下面是使用 sklearn 中的 SGDClassifier 实现拍卖是否成功的模型训练代码

from sklearn.linear_model import SGDClassifier
from sklearn.preprocessing import StandardScaler

# The results of mini_batch learning for SGDClassifier in the training process were drawn
def plot_learning(clf,title):
    plt.figure()
    
    # Record the prediction of the last training result in this training
    validationScore = []
    # Record the forecast situation after adding this training result
    trainScore = []
    # Minimum training frequency
    mini_batch = 1000
    for i in range(int(np.ceil(n_trainSamples / mini_batch))):
        x_batch = train_data[i * mini_batch : min((i + 1) * mini_batch, n_trainSamples)]
        y_batch = train_target[i * mini_batch: min((i + 1) * mini_batch, n_trainSamples)]
        
        if i > 0:
            validationScore.append(clf.score(x_batch, y_batch))
        clf.partial_fit(x_batch, y_batch, classes = range(5))
        if i > 0:
            trainScore.append(clf.score(x_batch, y_batch))
        plt.plot(trainScore, label = "train_score")
        plt.plot(validationScore, label = "validation_score")
        plt.xlabel("Mini_batch")
        plt.ylabel("Score")
        plt.grid()
        plt.title(title)
        plt.savefig('test.jpg')

# Normalized data
scaler = StandardScaler()
train_data = scaler.fit_transform(train_data.drop(['EndDay'], axis = 1))

# Create SGDClassifier
clf = SGDClassifier(penalty = 'l2', alpha = 0.001)
plot_learning(clf, 'SGDClassifier')

训练结果如下图,由于 SGDClassifier 是在所有的训练样本中抽取一部分作为本次训练集,因此这里不适用 Cross Validation(交叉验证)
scikit-learn实现ebay数据分析 可以看到 SGDClassifier 的训练效果还不错,准确率几乎达到92%。我们可以继续使用 scikit-learn 中封装的一些降维方法,这里我们使用三种方法进行降维—— RandomProjectionPCAT-SNE embedding

from sklearn import manifold, decomposition, random_projection
from matplotlib import offsetbox
from time import time

images = []
images.append([
    [0., 0., 5., 13., 9., 1., 0., 0.],
    [0., 0., 13., 15., 10., 15., 5., 0.],
    [0., 3., 15., 2., 0., 11., 8., 0.],
    [0., 4., 12., 0., 0., 8., 8., 0.],
    [0., 5., 8., 0., 0., 9., 8., 0.],
    [0., 4., 11., 0., 1., 12., 7., 0.],
    [0., 2., 14., 5., 10., 12., 0., 0.],
    [0., 0., 6., 13., 10., 0., 0., 0.]
])
images.append([
    [0., 0., 0., 12., 13., 5., 0., 0.],
    [0., 0., 0., 11., 16., 9., 0., 0.],
    [0., 0., 3., 15., 16., 6., 0., 0.],
    [0., 7., 15., 16., 16., 2., 0., 0.],
    [0., 0., 1., 16., 16., 3., 0., 0.],
    [0., 0., 1., 16., 16., 6., 0., 0.],
    [0., 0., 1., 16., 16., 6., 0., 0.],
    [0., 0., 0., 11., 16., 10., 0., 0.]
])
# 1000 pieces of data were selected for visual display
show_instances = 1000

# define the drawing function
def plot_embedding(X, title = None):
    x_min, x_max = np.min(X, 0), np.max(X, 0)
    X = (X - x_min) / (x_max - x_min)
    
    plt.figure()
    ax = plt.subplot(111)
    for i in range(X.shape[0]):
        plt.text(X[i,0], X[i,1], str(train_target[i]),
                 color = plt.cm.Set1(train_target[i] / 2.),
                 fontdict = {'weight':'bold','size':9})
    if hasattr(offsetbox, 'AnnotationBbox'):
        shown_images = np.array([
            [1., 1.]
        ])
    for i in range(show_instances):
        dist = np.sum((X[i] - shown_images) ** 2, 1)
        if np.min(dist) < 4e-3:
            # don't show points that are too close
            continue
        shown_images = np.r_[shown_images, [X[i]]]
        auctionbox = offsetbox.AnnotationBbox(
            offsetbox.OffsetImage(images[train_target[i]], cmap = plt.cm.gray_r), X[i]
        )
        ax.add_artist(auctionbox)
    plt.xticks([]), plt.yticks([])
    if title is not None:
        plt.title(title)
        
# Random Projuection
start_time = time()
rp = random_projection.SparseRandomProjection(n_components = 2,random_state = 50)
rp.fit(train_data[:show_instances])
train_projected = rp.transform(train_data[:show_instances])
plot_embedding(train_projected, "Random Projecion of the auction (time: %.3fs)" % (time() - start_time))

# PCA
start_time = time()
train_pca = decomposition.TruncatedSVD(n_components = 2).fit_transform(train_data[:show_instances])
plot_embedding(train_projected, "Pricincipal Components Projection of the auction (time: %.3fs)" % (time() - start_time))

# t-sns
start_time = time()
tsne= manifold.TSNE(n_components = 2, init = 'pca', random_state = 0)
train_tsne = tsne.fit_transform(train_data[:show_instances])
plot_embedding(train_projected, "T-SNE embedding of the auction (time: %.3fs)" % (time() - start_time))

随机投影效果如下图

scikit-learn实现ebay数据分析

PCA降维效果

scikit-learn实现ebay数据分析

T-SNE降维效果

scikit-learn实现ebay数据分析

从上面三幅图中,我们可以看出数字0和1的重叠情况,判断出数据的可区分度并不是特别大,因此我们训练效果也并没有特别好

分类训练结束后,查看分类器在测试集上的效果

from sklearn.metrics import precision_score, recall_score, f1_score

train_data = scaler.fit_transform(train_data)

train_pred = clf.predict(train_data)

print("SGDClassifier training performance on testing dataset:")
print("\tPrecision:%1.3f" % precision_score(train_target, train_pred))
print("\tRecall:%1.3f" % recall_score(train_target, train_pred))
print("\tF1:%1.3f \n" % f1_score(train_target, train_pred))

测试效果:

SGDClassifier training performance on testing dataset:
    Precision:0.875
    Recall:0.730
    F1:0.796

预测拍卖最终成交价格

由于价格Price是一个 Numerical 的值,而拍卖是否成功是一个 Category 的值,因此两者做法是不一样的,预测价格是一个 回归 任务,而判断拍卖是否成功是一个 分类 任务

同样根据 机器学习算法使用图谱 ,这里我们采取 SGDRegressor ,代码如下:

from sklearn.linear_model import SGDRegressor
import random
from sklearn.preprocessing import MinMaxScaler

# prepare data
test_subset = pd.read_csv('Data/TestSubset.csv')
train_subset = pd.read_csv('Data/TrainingSubset.csv')

# Training Data
train = train_subset.drop(['EbayID','Price','SellerName','EndDay'],axis=1)
train_target = train_subset['Price']

scaler = MinMaxScaler()
train = scaler.fit_transform(train)
n_trainSamples, n_features = train.shape

# ploting example from scikit-learn
def plot_learning(clf,title):

    plt.figure()
    validationScore = []
    trainScore = []
    mini_batch = 500
    # define the shuffle index
    idx = list(range(n_trainSamples))
    random.shuffle(idx)

    for i in range(int(np.ceil(n_trainSamples / mini_batch))):
        x_batch = train[idx[i * mini_batch: min((i + 1) * mini_batch, n_trainSamples)]]
        y_batch = train_target[idx[i * mini_batch: min((i + 1) * mini_batch, n_trainSamples)]]

        if i > 0:
            validationScore.append(clf.score(x_batch, y_batch))
        clf.partial_fit(x_batch, y_batch)
        if i > 0:
            trainScore.append(clf.score(x_batch, y_batch))

    plt.plot(trainScore, label="train score")
    plt.plot(validationScore, label="validation socre")
    plt.xlabel("Mini_batch")
    plt.ylabel("Score")
    plt.legend(loc='best')
    plt.title(title)

sgd_regresor = SGDRegressor(penalty='l2',alpha=0.001)
plot_learning(sgd_regresor,"SGDRegressor")

# 准备测试集查看测试情况
test = test_subset.drop(['EbayID','Price','SellerName','EndDay'],axis=1)
test = scaler.fit_transform(test)
test_target = test_subset['Price']

print("SGD regressor prediction result on testing data: %.3f" % sgd_regresor.score(test,test_target))

plt.show()

scikit-learn实现ebay数据分析 在测试集上的测试结果: SGD regressor prediction result on testing data: 0.936 ,由于 SGDRegressor 回归效果不错,因此就不太需要进一步选择其他的模型进行尝试了

总结

本篇文章大概讲解了如何使用 scikit-learn 进行数据分析,其实在数据分析过程中,运用到 机器学习 的算法进行模型训练并不是最重要的,大量的时间花费在数据的 预处理 上,我不止一次听到很多机器学习大牛说过一句话 数据分析,最重要的不是算法,是数据 。关于更多 scikit-learn 的机器学习算法,可以查看 官方文档 ,上面有很多例子,可以帮助大家快速入门


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Essential PHP Security

Essential PHP Security

Chris Shiflett / O'Reilly Media / 2005-10-13 / USD 29.95

Being highly flexible in building dynamic, database-driven web applications makes the PHP programming language one of the most popular web development tools in use today. It also works beautifully wit......一起来看看 《Essential PHP Security》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具