数据分析---众包任务

20 篇文章 1 订阅
15 篇文章 1 订阅

前言

依然是记录一次我的近期作业,这个做了一天半才做完,昨天通宵去拟合函数结果还是不理想,耽误了太多时间。主要原因还是昨天取的特征值太少了导致一直欠拟合,当然数据的分布也确实不太友好,先来看看这次的任务背景和任务要求。
在这里插入图片描述
在这里插入图片描述
然后需要我们计算十二个指标
在这里插入图片描述
任务流程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
现在熟悉了任务背景和流程要求,就开始动手。(其实这个案例前半部分是教我们如何用循环去得到指标的,这部分我就不贴了)

开始动手

1.导入数据,查看并且计算指标

import pandas as pd
import numpy as np
import math
import warnings
warnings.filterwarnings("ignore")

A=pd.read_excel('./第9次作业 已结束项目任务数据.xls')
B=pd.read_excel('./第9次作业 会员信息数据.xlsx')

A.info()
A.head()

B.info()
B.head()

在这里插入图片描述
在这里插入图片描述
数据集就是这个样子,每一个属性的意义也很清楚,数据本身其实也很干净,所以我就没有进行数据预处理直接去计算要求的指标了。

#将B转换为时间序列
B['预订任务开始时间']= pd.to_datetime(B['预订任务开始时间'],format = '%H:%M:%S')
B.info()
B.head()

# 开始得到Z1-Z12
Z=np.zeros((len(A),12))
for q in range(len(A)):
    A_Wq=A.iloc[q,1]
    A_Jq=A.iloc[q,2]

    D1=np.zeros((len(A)))
    D2=np.zeros((len(B)))

    for t in range(len(A)):
        A_Wt=A.iloc[t,1]
        A_Jt=A.iloc[t,2]
        dt=111.19*math.sqrt((A_Wq-A_Wt)**2+(A_Jq-A_Jt)**2*math.cos((A_Wq+A_Wt)*math.pi/180)**2)
        D1[t]=dt

    for k in range(len(B)):
        B_Wk=B.iloc[k,1]
        B_Jk=B.iloc[k,2]
        dk=111.19*math.sqrt((A_Wq-B_Wk)**2+(A_Jq-B_Jk)**2*math.cos((A_Wq+B_Wk)*math.pi/180)**2)
        D2[k]=dk

    Z1=len(D1[D1<=5])-1   #5公里内其他任务量
    Z2=A.iloc[D1<=5,[3]].mean()[0]  #5公里内的平均价格
    Z3=B.iloc[D2<=5,[3]].sum()[0]   #5公里内可预订任务量 
    Z4=B.iloc[D2<=5,[3,5]].sum()[1]/len(D2[D2<=5])  #5公里内信誉平均值
    Z5=len(D2[D2<=5])  #5公里内会员个数    
    #下面是不同时间段内的任务量
    Z6=B.iloc[D2<=5,[3,4]][(B['预订任务开始时间']==pd.to_datetime('06:30:00',format='%H:%M:%S'))]['预订任务限额'].sum()
    Z7=B.iloc[D2<=5,[3,4]][(B['预订任务开始时间']>=pd.to_datetime('06:33:00',format='%H:%M:%S'))&(B['预订任务开始时间']<=pd.to_datetime('06:45:00',format='%H:%M:%S'))]['预订任务限额'].sum()
    Z8=B.iloc[D2<=5,[3,4]][(B['预订任务开始时间']>=pd.to_datetime('06:48:00',format='%H:%M:%S'))&(B['预订任务开始时间']<=pd.to_datetime('07:03:00',format='%H:%M:%S'))]['预订任务限额'].sum()
    Z9=B.iloc[D2<=5,[3,4]][(B['预订任务开始时间']>=pd.to_datetime('07:06:00',format='%H:%M:%S'))&(B['预订任务开始时间']<=pd.to_datetime('07:21:00',format='%H:%M:%S'))]['预订任务限额'].sum()
    Z10=B.iloc[D2<=5,[3,4]][(B['预订任务开始时间']>=pd.to_datetime('07:24:00',format='%H:%M:%S'))&(B['预订任务开始时间']<=pd.to_datetime('07:39:00',format='%H:%M:%S'))]['预订任务限额'].sum()
    Z11=B.iloc[D2<=5,[3,4]][(B['预订任务开始时间']>=pd.to_datetime('07:42:00',format='%H:%M:%S'))&(B['预订任务开始时间']<=pd.to_datetime('07:57:00',format='%H:%M:%S'))]['预订任务限额'].sum()
    Z12=B.iloc[D2<=5,[3,4]][(B['预订任务开始时间']==pd.to_datetime('08:00:00',format='%H:%M:%S'))]['预订任务限额'].sum()
    
    Z[q,0]=Z1
    Z[q,1]=Z2
    Z[q,2]=Z3
    Z[q,3]=Z4
    Z[q,4]=Z5
    Z[q,5]=Z6
    Z[q,6]=Z7
    Z[q,7]=Z8
    Z[q,8]=Z9
    Z[q,9]=Z10
    Z[q,10]=Z11
    Z[q,11]=Z12

    
data=pd.DataFrame(Z)
print(data.head())
data.to_csv("第九次作业指标.csv",index=False,encoding="utf-8")

对于时间的截取我也不太熟悉,所以用的是这种比较笨的截取方法。然后把得到的数据保存到csv文件,避免我们每次都要算一次这个。(因为我们后面计算有可能会导致电脑卡死然后restart kernel,所以保存一下比较好)

2.导入我们得到的指标,并且进行主成分分析

data=pd.read_csv('./第九次作业指标.csv')
data.info()
data.head()

在这里插入图片描述
然后我后面报错,发现有缺失值,所以先来填补一次

# 填补缺失值
data.fillna(0,inplace=True)
data.astype(float)
data.info()
data.head()

相关性分析

# 进行相关性计算,并可视化一下
import matplotlib.pyplot as plt
import seaborn as sns

plt.rcParams['font.family']='FangSong'
plt.rcParams['axes.unicode_minus']=False

sns.pairplot(data)
plt.show()

sns.heatmap(data.corr())
plt.show()

在这里插入图片描述
在这里插入图片描述
主成分分析

# 进行主成分分析,使得累计贡献率达到90%以上
from sklearn.decomposition import PCA

res=[]
for i in range(1,10):
    pca=PCA(n_components=i)
    pca.fit(data)
    res.append(pca.explained_variance_ratio_.sum())
    
plt.plot([i for i in range(1,10)],res)
plt.title("不同主成分数目下的累计贡献率")
plt.xlabel("主成分数目")
plt.ylabel("贡献率")
plt.show()

在这里插入图片描述
然后我也试了一下让它自己选择降维数

#让他自己选择数目看下是否符合要求
pca=PCA(n_components='mle')
pca.fit(data)
print("主成分数目为:",pca.n_components_)
print("累计贡献率为:",pca.explained_variance_ratio_.sum())
print("特征值为:",pca.get_covariance())

在这里插入图片描述
发现11就行(为了后面提高拟合效果,我这里尽量选多点)

#由上面的贡献率来看取11个主成分就好
pca=PCA(n_components=11)
trans_data=pca.fit_transform(data)
print(pca.explained_variance_ratio_.sum())
# 各个主成分的贡献率可视化
plt.figure()
plt.bar([i for i in range(trans_data.shape[1])],pca.explained_variance_ratio_)
plt.title("各个主成分的贡献率")
plt.xlabel("主成分")
plt.ylabel("贡献率")
plt.show()

print("主成分数目为11时特征向量为:",pca.components_)

在这里插入图片描述
特征向量如下,由特征向量就能得到主成分表达式了(矩阵相乘)
在这里插入图片描述

3.添加主成分数据,进行拟合

# 然后我们把得到的主成分添加到已结束任务数据的表中
trans_data=pd.DataFrame(trans_data,
                        columns=['主成分1','主成分2','主成分3','主成分4','主成分5','主成分6','主成分7','主成分8','主成分9','主成分10','主成分11'])
trans_data.head()

data=pd.merge(A,trans_data,how='left',left_index=True,right_index=True)
finished=data[data['任务执行情况']==1]
finished.head()

在这里插入图片描述

#以主成分为自变量,任务标价为因变量探索是否为线性关系
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

X=finished[['主成分1','主成分2','主成分3','主成分4','主成分5','主成分6','主成分7','主成分8','主成分9','主成分10','主成分11']]
Y=finished['任务标价']

sns.jointplot(X['主成分1'],Y,kind='reg')
sns.jointplot(X['主成分2'],Y,kind='reg')
sns.jointplot(X['主成分3'],Y,kind='reg')
sns.jointplot(X['主成分4'],Y,kind='reg')
sns.jointplot(X['主成分5'],Y,kind='reg')
plt.show()

在这里插入图片描述
由图看得出其实并不是线性关系,然后就有了我下面的尝试

# 先用多元回归拟合试试

#对X标准化处理
scaler=StandardScaler().fit(X)
X=scaler.transform(X)

X_train, X_test, y_train, y_test = train_test_split(X,Y, test_size=0.2, random_state=2)
from sklearn.metrics import r2_score

linreg = LinearRegression()
linreg.fit(X_train,y_train)
y_pred = linreg.predict(X_test)
print(linreg.score(X_test,y_test))
# 可视化看看测试集拟合效果
plt.figure()
plt.plot([i for i in range(len(X_test))],y_pred,label='拟合曲线')
plt.plot([i for i in range(len(X_test))],y_test,label='真实曲线')
plt.title("测试集拟合效果")
plt.legend()
plt.show()


#增加高次项再看看拟合效果
quadratic_fearurizer = PolynomialFeatures(degree=2)
X_train_quadratic = quadratic_fearurizer.fit_transform(X_train)
X_test_quadratic = quadratic_fearurizer.transform(X_test)
linreg = LinearRegression()
linreg.fit(X_train_quadratic,y_train)

y_train_pred=linreg.predict(X_train_quadratic)
y_pred = linreg.predict(X_test_quadratic)
print(linreg.score(X_train_quadratic,y_train))
print(linreg.score(X_test_quadratic,y_test))

# 可视化看看训练集拟合效果
plt.figure()
plt.plot([i for i in range(len(X_train))],y_train_pred,label='拟合曲线')
plt.plot([i for i in range(len(X_train))],y_train,label='真实曲线')
plt.title("训练集拟合效果")
plt.legend()
plt.show()


# 可视化看看测试集拟合效果
plt.figure()
plt.plot([i for i in range(len(X_test))],y_pred,label='拟合曲线')
plt.plot([i for i in range(len(X_test))],y_test,label='真实曲线')
plt.title("测试集拟合效果")
plt.legend()
plt.show()

添加了二次项后拟合的效果
在这里插入图片描述
不太理想,再试试其他的

#试试mlp
from sklearn.neural_network import MLPRegressor

para_dict ={'alpha':10**-np.arange(-7,0),'hidden_layer_sizes':[10,20,50,100,150,200]}


model_mlp = MLPRegressor(
    solver='lbfgs', alpha=1e-5,hidden_layer_sizes=(5,10), random_state=1,
    activation='relu', learning_rate='adaptive',max_iter=5000
)
gcv = GridSearchCV(model_mlp,param_grid=para_dict ,cv = 5,n_jobs=-1)

gcv.fit(X_train, y_train)

mlp_score=gcv.score(X_test,y_test)
print('回归模型得分',mlp_score)
y_pred = gcv.predict(X_test)
# 可视化看看测试集拟合效果
plt.figure()
plt.plot([i for i in range(len(X_test))],y_pred,label='拟合曲线')
plt.plot([i for i in range(len(X_test))],y_test,label='真实曲线')
plt.title("测试集拟合效果")
plt.legend()
plt.show()

在这里插入图片描述
多层感知机好一点,但是效果还是不太好。当然我也试了BP(用了一个通宵,效果依然很差!!!到了一定时候梯度下降就无法降低损失,陷入局部最优解了)
在这里插入图片描述
从这个定价分布来看,其实没有任何明显的关系,数据太随机了所以没有很好的拟合效果也是情有可原,然后我用了svr去拟合,一番调参过后效果是最好的,所以我就用的svr去回归预测。
在这里插入图片描述

4.用svr给未完成的任务重新定价

unfinished=data[data['任务执行情况']==0]
unfinished.head()

X=unfinished[['主成分1','主成分2','主成分3','主成分4','主成分5','主成分6','主成分7','主成分8','主成分9','主成分10','主成分11']]
scaler=StandardScaler().fit(X)
X=scaler.transform(X)

Y=svr.predict(X)
unfinished['重新定价']=Y
unfinished.head()

在这里插入图片描述
在这里插入图片描述

5.用原价格和主成分去训练SVM分类模型

# 使用svm对所有数据训练分类模型
# 划分数据集
X=data[['任务标价','主成分1','主成分2','主成分3','主成分4','主成分5','主成分6','主成分7','主成分8','主成分9','主成分10','主成分11']]
Y=data['任务执行情况']
Y=np.array(Y).reshape(-1,1)
scaler=StandardScaler().fit(X)
X=scaler.transform(X)

X_train, X_test, y_train, y_test = train_test_split(X,Y, test_size=0.2, random_state=2)
print(X_train.shape,y_test.shape)
from sklearn.svm import SVC
from sklearn import metrics as sm


svm=SVC()
parameters=[{'kernel': ['linear','rbf','poly'],'C': [0.01,0.1,1,10],'gamma':[0.001,0.01,0.1,1,10],'degree':[2,3,4,5,6,7]}]
clf = GridSearchCV(svm,parameters,scoring='accuracy',cv=5,n_jobs=-1)
clf.fit(X_train, y_train)

svm=clf.best_estimator_
svm.fit(X_train,y_train)
y_pred=svm.predict(X_test)

matrix=sm.confusion_matrix(y_test,y_pred)
report=sm.classification_report(y_test,y_pred)

def plot_confusion_matrix(confusion_mat):
    df_cm = pd.DataFrame(confusion_mat,index=[1,2],columns=[1,2])
    ax = sns.heatmap(df_cm,annot=True,fmt='.20g')
    ax.set_title('混淆矩阵')
    ax.set_xlabel('预测标签')
    ax.set_ylabel('真实标签')
    plt.show()
    
plot_confusion_matrix(matrix)
print(report)

在这里插入图片描述
模型效果依然不是特别好,准确率和f1分数都不是特别高。期待着后期能有优化,但是现在的我只想早点做完。最近因为忙着写作业都快一周没有怎么看考研相关的了,老师也原谅一下我偷懒啦

6.用刚刚训练好的SVM对新的价格和特征做预测

# 对未执行任务中新的定价以及主成分用svm做预测
X=unfinished[['重新定价','主成分1','主成分2','主成分3','主成分4','主成分5','主成分6','主成分7','主成分8','主成分9','主成分10','主成分11']]
scaler=StandardScaler().fit(X)
X=scaler.transform(X)

y_pred=svm.predict(X)
unfinished['新的完成情况']=y_pred
unfinished.head()

在这里插入图片描述

7.模型评价

看看新的定价情况下,任务完成数会增加多少,另外新的定价比原始定价会增加多少金额

把表格中所有新的完成情况为1的统计,然后再把价格作差

new_finish_num=unfinished[unfinished['新的完成情况']==1]['新的完成情况'].sum()
increase_price=unfinished['重新定价'].sum()-unfinished['任务标价'].sum()
print("新增加的完成数:",new_finish_num)
print("新增加的价格:",increase_price)

在这里插入图片描述
增加的金额27.5小于50,任务完成数增加了89,达到了要求。

最后

最近真的太累了,我只想安安心心的复习考研,但是事情又太多,比赛、作业,太难了。所以这个作业其实做的很应付,我一般都比较喜欢追求完美的,但是后来慢慢发现事情太多了没办法把每件事都做到最好,还是要分重要的去做。

模型的误差问题
SVR拟合的R2只有0.58,SVM的准确率也只有0.82,所以虽然最后的结果满足了条件,但是并不能很好的说明问题。不过有一点,钱多人就愿意做事这个道理还是体现的很深刻的。至于优化的话,等我复习累了我会去想想怎么提高回归拟合程度。

  • 12
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

shelgi

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

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

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

打赏作者

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

抵扣说明:

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

余额充值