Python业务分析实战|共享单车数据挖掘
本文詳細介紹了共享單車數據挖掘,包括數據分析和模型開發。它包含以下步驟:
數據集簡介
關于共享單車數據集
自行車共享系統是傳統自行車租賃的新一代,從注冊會員、租賃到歸還的整個過程都是自動化的。通過這些系統,用戶可以很容易地從一個特定的位置租用自行車,并在另一個位置歸還。目前,全球大約有500多個共享單車項目,這些項目由50多萬輛自行車組成。今天,由于它們在交通、環境和健康問題上的重要作用,人們對這些系統產生了極大的興趣。
除了自行車共享系統在現實世界的有趣應用之外,眾多研究者們對這些系統所產生的數據產生濃厚的興趣。與其他運輸服務(如公共汽車或地鐵)不同,共享自行車使用的持續時間、出發時間和到達位置都明確地記錄在系統中。這一功能將自行車共享系統變成了一個虛擬傳感器網絡,可用于感知城市中的流動性。因此,通過監測這些數據,預計可以檢測到城市中的大多數重要事件。
今天我們就運用這些數據集,挖掘出蘊含在其中的有效的信息。接下來從探索數據屬性,清洗數據,到模型開發,一起來學習,共同進步。
注意,該數據集是國外共享單車數據集,并非國內的共享單車數據集。但不影響我們學習數據挖掘相關知識和技術。數據集獲取可以聯系原文作者云朵君(Mr_cloud_data)獲取。
屬性信息
hour.csv和?day.csv都有以下字段,day.csv中沒有?hr?字段
instant:記錄索引
dteday?:日期
season?:季節 (1:春天, 2:夏天, 3:秋天, 4:冬天)
yr?:年份 (0:2011, 1:2012)
mnth:月份 ( 1 to 12)
hr:小時 (0 to 23)
holiday?:是否是假期
weekday?:星期幾
workingday?:工作日,如果日既不是周末也不是假日,則為1,否則為0。
weathersit:
1:晴,少云,部分云,無云
2:薄霧+多云,薄霧+碎云,薄霧+少量云,薄霧
3:小雪,小雨+雷暴+散云,小雨+散云
4:大雨+冰板+雷暴+霧,雪+霧
temp:標準化溫度數據,單位為攝氏度。這些值是通過(t-t_min)/(t_max-t_min, t_min=-8, t_max=+39(僅在小時范圍內)得到的
atemp:以攝氏度為單位的正常體感溫度。這些值是通過(t-t_min)/(t_max-t_min), t_min=-16, t_max=+50(僅在小時范圍內)得到的
hum:標準化濕度。這些值被分割到100(最大值)
windspeed:歸一化的風速數據。這些值被分割到 67 (最大值)
casual:注銷用戶數量
registered:已注冊用戶數量
cnt:出租自行車總數,包括注銷和注冊自行車
前期準備
導入模塊
import?seaborn?as?sns import?matplotlib.pyplot?as?plt from?prettytable?import?PrettyTable import?numpy?as?np import?pandas?as?pd from?sklearn.model_selection?import?RandomizedSearchCV from?sklearn.metrics?import?mean_squared_error,?mean_absolute_error,?mean_squared_log_error from?sklearn.linear_model?import?Lasso,?ElasticNet,?Ridge,?SGDRegressor from?sklearn.svm?import?SVR,?NuSVR from?sklearn.ensemble?import?BaggingRegressor,?RandomForestRegressor from?sklearn.neighbors?import?KNeighborsClassifier from?sklearn.cluster?import?KMeans from?sklearn.ensemble?import?RandomForestClassifier from?sklearn.ensemble?import?GradientBoostingClassifier from?sklearn.linear_model?import?LinearRegression import?random %matplotlib?inlinerandom.seed(100)定義數據獲取函數
class?Dataloader():'''自行車共享數據集數據加載器。'''def?__init__(self,?csv_path):'''?初始化自行車共享數據集數據加載器。param:?csv_path?{str}?--?自行車共享數據集CSV文件的路徑。'''self.csv_path?=?csv_pathself.data?=?pd.read_csv(self.csv_path)#?Shuffleself.data.sample(frac=1.0,?replace=True,?random_state=1)def?getHeader(self):'''?獲取共享單車CSV文件的列名。return:?[list?of?str]--CSV文件的列名'''return?list(self.data.columns.values)def?getData(self):'''???劃分訓練、驗證和測試集返回:?pandas?DataFrames--?劃分后的不同數據集pandas?DataFrames'''#?將數據按60:20:20的比例劃分為訓練、驗證和測試集split_train?=?int(60?/?100?*?len(self.data))?split_val?=?int(80?/?100?*?len(self.data))?train?=?self.data[:split_train]val?=?self.data[split_train:split_val]test?=?self.data[split_val:]return?train,?val,??testdef?getFullData(self):'''?在一個DataFrames中獲取所有數據。return:?pandas?DataFrames--?完整的共享數據集數據'''return?self.data描述性分析
劃分訓練、驗證和測試數據集
dataloader?=?Dataloader('../data/bike/hour.csv') train,?val,?test?=?dataloader.getData() fullData?=?dataloader.getFullData()category_features?=?['season',?'holiday',?'mnth',?'hr',? 'weekday',?'workingday',?'weathersit'] number_features?=?['temp',?'atemp',?'hum',?'windspeed']features=?category_features?+?number_features target?=?['cnt']features['season','holiday','mnth','hr','weekday','workingday','weathersit','temp','atemp','hum','windspeed']獲取DataFrame的列名:
print(list(fullData.columns))['instant', 'dteday', 'season', 'yr', 'mnth', 'hr', 'holiday', 'weekday', 'workingday', 'weathersit', 'temp', 'atemp', 'hum', 'windspeed', 'casual', 'registered', 'cnt']打印數據集的前五個示例來探索數據:
fullData.head(5)獲取每列的數據統計信息:
fullData[number_features].describe()for?col?in?category_features:fullData[col]?=?fullData[col].astype('category') fullData[category_features].describe()缺失值分析
缺失值分析可參見往期文章:缺失值處理,你真的會了嗎?
檢查數據中的NULL值:
print(fullData.isnull().any())instant False dteday False season False yr False mnth False hr False holiday False weekday False workingday False weathersit False temp False atemp False hum False windspeed False casual False registered False cnt False dtype:bool異常值分析
箱形圖
sns.set(font_scale=1.0) fig,?axes?=?plt.subplots(nrows=3,ncols=2) fig.set_size_inches(15,?15) sns.boxplot(data=train,y="cnt",orient="v",ax=axes[0][0]) sns.boxplot(data=train,y="cnt",x="mnth",orient="v",ax=axes[0][1]) sns.boxplot(data=train,y="cnt",x="weathersit",orient="v",ax=axes[1][0]) sns.boxplot(data=train,y="cnt",x="workingday",orient="v",ax=axes[1][1]) sns.boxplot(data=train,y="cnt",x="hr",orient="v",ax=axes[2][0]) sns.boxplot(data=train,y="cnt",x="temp",orient="v",ax=axes[2][1])axes[0][0].set(ylabel='Count',title="Box?Plot?On?Count") axes[0][1].set(xlabel='Month',?ylabel='Count',title="Box?Plot?On?Count?Across?Months") axes[1][0].set(xlabel='Weather?Situation',?ylabel='Count',title="Box?Plot?On?Count?Across?Weather?Situations") axes[1][1].set(xlabel='Working?Day',?ylabel='Count',title="Box?Plot?On?Count?Across?Working?Day") axes[2][0].set(xlabel='Hour?Of?The?Day',?ylabel='Count',title="Box?Plot?On?Count?Across?Hour?Of?The?Day") axes[2][1].set(xlabel='Temperature',?ylabel='Count',title="Box?Plot?On?Count?Across?Temperature")for?tick?in?axes[2][1].get_xticklabels():tick.set_rotation(90)解析:?工作日和節假日箱形圖表明,正常工作日出租的自行車比周末或節假日多。每小時的箱形圖顯示當地早上8點最大,下午5點最大,這表明大多數自行車租賃服務的用戶使用自行車上班或上學。另一個重要因素似乎是溫度:較高的溫度導致自行車租賃數量增加,而較低的溫度不僅降低了平均租賃數量,而且在數據中顯示出更多的異常值。
從數據中去除異常值
sns.distplot(train[target[-1]]);計數值的分布圖顯示,計數值不符合正態分布。我們將使用中位數和四分位區間(IQR)來識別和去除數據中的異常值。(另一種方法是將目標值轉換為正態分布,并使用平均值和標準偏差。)
print("帶有異常值的列車集合中的樣本:?{}".format(len(train))) q1?=?train.cnt.quantile(0.25) q3?=?train.cnt.quantile(0.75) iqr?=?q3?-?q1 lower_bound?=?q1?-(1.5?*?iqr)? upper_bound?=?q3?+(1.5?*?iqr)? train_preprocessed?=?train.loc[(train.cnt?>=?lower_bound)?&?(train.cnt?<=?upper_bound)] print("沒有異常值的訓練樣本集:?{}".format(len(train_preprocessed))) sns.distplot(train_preprocessed.cnt);帶有異常值的列車集合中的樣本:10427 沒有異常值的訓練樣本集:10151相關分析
matrix?=?train[number_features?+?target].corr() heat?=?np.array(matrix) heat[np.tril_indices_from(heat)]?=?False fig,ax=?plt.subplots() fig.set_size_inches(15,8) sns.set(font_scale=1.0) sns.heatmap(matrix,?mask=heat,vmax=1.0,?vmin=0.0,?square=True,annot=True,?cmap="Reds")結論:?在描述性分析總結如下幾點:
變量"Casual"和"registered"包含關于共享自行車計數直接信息,而如果將這些信息用于預測(數據泄漏)。因此,它們不在特征集中考慮。
變量"temp"和"atemp"是高度相關的。為了降低預測模型的維數,可以刪除特征"atemp"。
變量"hr"和"temp"似乎是預測自行車共享數量的貢獻較大的特征。
評價指標概述
Mean Squared Error (MSE)
()
Root Mean Squared Logarithmic Error (RMSLE)
(()())
R^2 Score
()
模型選擇
所呈現的問題的特點是:
回歸:目標變量是一個連續型數值。
數據集小:小于100K的樣本量。
少數特征應該是重要的:相關矩陣表明少數特征包含預測目標變量的信息。
這些特點給予了嶺回歸、支持向量回歸、集成回歸、隨機森林回歸等方法大展身手的好機會。有關回歸模型可參見往期文章👇。
線性回歸中的多重共線性與嶺回歸
機器學習 | 簡單而強大的線性回歸詳解
機器學習 | 深度理解Lasso回歸分析
一文掌握sklearn中的支持向量機
集成算法 | 隨機森林回歸模型
萬字長文,演繹八種線性回歸算法最強總結!
原理+代碼,總結了 11 種回歸模型
機器學習中回歸算法的基本數學原理
我們將對這些模型的性能進行如下評估:
x_train?=?train_preprocessed[features].values y_train?=?train_preprocessed[target].values.ravel() #?Sort?validation?set?for?plots val?=?val.sort_values(by=target) x_val?=?val[features].values y_val?=?val[target].values.ravel() x_test?=?test[features].valuestable?=?PrettyTable() table.field_names?=?["Model",?"Mean?Squared?Error",?"R2?score"]models?=?[SGDRegressor(max_iter=1000,?tol=1e-3),Lasso(alpha=0.1),ElasticNet(random_state=0),Ridge(alpha=.5),SVR(gamma='auto',?kernel='linear'),SVR(gamma='auto',?kernel='rbf'),BaggingRegressor(),BaggingRegressor(KNeighborsClassifier(),?max_samples=0.5,?max_features=0.5),NuSVR(gamma='auto'),RandomForestRegressor(random_state=0,?n_estimators=300) ]for?model?in?models:model.fit(x_train,?y_train)?y_res?=?model.predict(x_val)mse?=?mean_squared_error(y_val,?y_res)score?=?model.score(x_val,?y_val)????table.add_row([type(model).__name__,?format(mse,?'.2f'),?format(score,?'.2f')])print(table)+-----------------------+--------------------+----------+ |?????????Model?????????|?Mean?Squared?Error?|?R2?score?| +-----------------------+--------------------+----------+ |??????SGDRegressor?????|??????43654.10??????|???0.06???| |?????????Lasso?????????|??????43103.36??????|???0.07???| |???????ElasticNet??????|??????54155.92??????|??-0.17???| |?????????Ridge?????????|??????42963.88??????|???0.07???| |??????????SVR??????????|??????50794.91??????|??-0.09???| |??????????SVR??????????|??????41659.68??????|???0.10???| |????BaggingRegressor???|??????18959.70??????|???0.59???| |????BaggingRegressor???|??????52475.34??????|??-0.13???| |?????????NuSVR?????????|??????41517.67??????|???0.11???| |?RandomForestRegressor?|??????18949.93??????|???0.59???| +-----------------------+--------------------+----------+隨機森林
隨機森林模型
隨機森林模型理論和實踐可參考如下兩篇文章:
集成算法 | 隨機森林分類模型
集成算法 | 隨機森林回歸模型?
特征重要性
importances?=?model.feature_importances_ std?=?np.std([tree.feature_importances_?for?tree?in?model.estimators_],?axis=0) indices = np.argsort(importances)[::-1]#?打印出特征排序 print("Feature ranking:")for?f?in?range(x_val.shape[1]):print("%d.?feature?%s?(%f)"?%?(f?+?1,?features[indices[f]],?importances[indices[f]]))Feature ranking: 1. feature hr (0.633655) 2. feature temp (0.160043) 3. feature hum (0.049495) 4. feature workingday (0.046797) 5. feature weathersit (0.027105) 6. feature windspeed (0.026471) 7. feature weekday (0.020293) 8. feature mnth (0.019940) 9. feature season (0.012995) 10. feature holiday (0.003206)#?繪制出隨機森林的特征重要性 plt.figure(figsize=(14,5)) plt.title("Feature?importances") plt.bar(range(x_val.shape[1]),?importances[indices],?color="cornflowerblue",?yerr=std[indices],?align="center") plt.xticks(range(x_val.shape[1]),?[features[i]?for?i?in?indices]) plt.xlim([-1,?x_val.shape[1]]) plt.show())解析:?結果對應于特征相關矩陣中變量"hour"和變量"temperature"與自行車共享計數的高度相關。
寫在最后
以下是進一步提高數據模型性能的一些思路:
目標變量的分布調整:有些預測模型假設目標變量的分布為正態分布,在數據預處理中進行轉換可以提高這些方法的性能。
大規模數據集隨機森林的實現。對于大規模數據集(>10 Mio. 樣本),如果不能在工作內存中保存所有的樣本,或者會遇到嚴重的內存問題,那么使用python實現sklearn中的隨機森林將會非常慢。一個解決方案可以是woody實現,其中包含用于預分類的頂樹,以及在頂樹的葉子處用C語言實現的平坦隨機森林。
本站qq群554839127,加入微信群請掃碼:
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Python业务分析实战|共享单车数据挖掘的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【推荐系统】基于知识图谱的推荐系统总结
- 下一篇: warnings (imported a