數據分析---衆包任務

前言

依然是記錄一次我的近期作業,這個做了一天半才做完,昨天通宵去擬合函數結果還是不理想,耽誤了太多時間。主要原因還是昨天取的特徵值太少了導致一直欠擬合,當然數據的分佈也確實不太友好,先來看看這次的任務背景和任務要求。
在這裏插入圖片描述
在這裏插入圖片描述
然後需要我們計算十二個指標
在這裏插入圖片描述
任務流程
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
現在熟悉了任務背景和流程要求,就開始動手。(其實這個案例前半部分是教我們如何用循環去得到指標的,這部分我就不貼了)

開始動手

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,所以雖然最後的結果滿足了條件,但是並不能很好的說明問題。不過有一點,錢多人就願意做事這個道理還是體現的很深刻的。至於優化的話,等我複習累了我會去想想怎麼提高迴歸擬合程度。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章