量化投資學習筆記19——回歸分析:實操,泰坦尼克號乘客生還機會預測,線性回歸方法。


用kaggle上的泰坦尼克的數據來實操。
https://www.kaggle.com/c/titanic/overview
在主頁上下載了數據。
任務:使用泰坦尼克號乘客數據建立機器學習模型,來預測乘客在海難中是否生存。
在實際海難中,2224位乘客中有1502位遇難了。似乎有的乘客比其它乘客更有機會獲救。本任務的目的就是找出哪類人更容易獲救。
數據集有兩個,一個是訓練數據集"train.csv",另一個是測試數據集"test.csv"。
官方推薦一個教程:https://www.kaggle.com/alexisbcook/titanic-tutorial
先照着來吧。
就是熟悉了整個結果上傳流程,使用了隨機樹森林算法,結果正確率是77.551%,排9444位。
接下來就是我自己折騰了。
讀取數據后,用info函數看看。

print(train_data.info())
print(test_data.info())

有三列數據有缺失值。先將數據可視化吧。

第一張是遇難者與獲救者的比例,第二張是三個票價等級的人數,第三張是遇難者及獲救者的年齡分布,第四張是按船票等級的年齡分布,最后一張是三個港口的登船人數。
再畫一個不同船票等級的乘客的獲救率。

可見高等級的獲救率更高。
再畫圖看性別與獲救的關系

真是lady first
下面再看各個艙別的獲救人數。

高等艙的女性生還率最高,其次是高等艙男性,低等艙男性生還率最低。
再看各港口登船的情況。

三個港口登船人數依次下降,死亡率差不多。
有堂兄弟妹,有子女父母對死亡率的影響。

 g = train_data.groupby(["SibSp", "Survived"])
 df = pd.DataFrame(g.count()["PassengerId"])
 print(df)
	
 g = train_data.groupby(["Parch", "Survived"])
 df = pd.DataFrame(g.count()["PassengerId"])
 print(df)

沒看出啥來。
Cabin缺失數據太多,畫圖看看數據缺失的和有數據的兩組死亡率是否有差別。

貌似有cabin記錄的獲救率高一些。
接下來就要清洗數據了,主要是處理缺失的數據,進行數據轉換。
(下面參考了https://blog.csdn.net/weixin_44451032/article/details/100103998)
先查看缺失值

print(train_data.isnull().sum())
print(test_data.isnull().sum())

主要是Age、Embarked和Cabin三個字段的缺失數據較多。
Age用年齡中位數填充,登船地點填充為眾數,Cabin則采用因子化,即根據有無Cabin數據分為兩類。

 train_data["Age"].fillna(train_data["Age"].median(), inplace = True)
 test_data["Age"].fillna(test_data["Age"].median(), inplace = True)
 train_data["Embarked"] = train_data["Embarked"].fillna('S')
 train_data.loc[(train_data.Cabin.notnull()), "Cabin"] = 1
 train_data.loc[(train_data.Cabin.isnull()), "Cabin"] = 0
 test_data.loc[(test_data.Cabin.notnull()), "Cabin"] = 1
 test_data.loc[(test_data.Cabin.isnull()), "Cabin"] = 0

再看看有沒有缺失數據的

行啦。
接下來把非數值數據轉換為數值數據
將性別數據轉換為數值數據

 train_data.loc[train_data["Sex"] == "male", "Sex"] = 0
 train_data.loc[train_data["Sex"] == "female", "Sex"] = 1
 test_data.loc[test_data["Sex"] == "male", "Sex"] = 0
 test_data.loc[test_data["Sex"] == "female", "Sex"] = 1

將登船地點數據轉換為數值數據

 C:0, Q:1, S:2
 train_data.loc[train_data["Embarked"] == 'C', "Embarked"] = 0
 train_data.loc[train_data["Embarked"] == 'Q', "Embarked"] = 1
 train_data.loc[train_data["Embarked"] == 'S', "Embarked"] = 2
 test_data.loc[test_data["Embarked"] == 'C', "Embarked"] = 0
 test_data.loc[test_data["Embarked"] == 'Q', "Embarked"] = 1
 test_data.loc[test_data["Embarked"] == 'S', "Embarked"] = 2
	
 print(train_data.head())
 print(test_data.head())

最后,提取我們認為在預測模型中重要的特征: Pclass,Sex,Age,Embarked,SibSp,Parch,Cabin
構建一個新的數據表。

columns = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Embarked', 'Survived', 'Cabin']
 new_train_data = train_data[columns]
 print(new_train_data.info())

OK,可以開始建模了。
先用剛學的線性回歸模型。
線性回歸模型
特征變量

 predictors = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Embarked', 'Cabin']
 LR = LinearRegression()

設置進行交叉驗證

 kf = KFold(5, random_state = 0)
 train_target = new_train_data["Survived"]
 accuracys = []
 for train, test in kf.split(new_train_data):
  LR.fit(new_train_data.loc[train, predictors], new_train_data.loc[train, "Survived"])
  pred = LR.predict(new_train_data.loc[test, predictors])
  pred[pred >= 0.6] = 1
  pred[pred < 0.6] = 0
  accuracy = len(pred[pred == new_train_data.loc[test, "Survived"]])/len(test)
  accuracys.append(accuracy)
 print(np.mean(accuracys))

結果:0.799083547799887
提交kaggle以后結果並不好。

再看看回歸的具體結果。

 print("回歸系數:", LR.coef_)
 print("截距:", LR.intercept_)
 X = new_train_data[predictors]
 y = new_train_data["Survived"]
 Y = LR.predict(X)
 print("模型評分:", LR.score(X, y))
 i = 241
 for index in predictors:
  X = new_train_data[index]
  fig = plt.subplot(i)
  i += 1
  plt.plot(X, Y, "*")
  plt.plot(X, y, "o")
 plt.savefig("LRtest.png")

結果:
回歸系數: [-0.13393963 0.50834201 -0.00505791 -0.03254537 -0.03019912 -0.02651349
0.11037934]
截距: 0.7106465692231267
0.40082362319192455
模型的R²才0.4(越接近1越理想)。

看着也沒啥聯系。再看看每個回歸系數的檢驗吧。sklearn里似乎沒有相關函數,還是用statsmodels模塊里的函數。

 # 看模型的假設檢驗
 X = new_train_data[predictors]
 X = sm.add_constant(X)
 model = sm.OLS(Y, X).fit()
 res = get_index(model)
 print("回歸參數", model.params)
 print("回歸結果", res)
 print(model.summary())

回歸系數跟用sklearn算的一樣,但檢驗結果卻特別好,有點詭異。可能是因為這個問題很多變量只有少數幾個值,甚至兩個值,是離散變量,不適合直接用線性回歸。
再試試其它方法。
本文代碼: https://github.com/zwdnet/MyQuant/tree/master/titanic
以后關於這個問題的代碼都放到這里面。

我發文章的四個地方,歡迎大家在朋友圈等地方分享,歡迎點“在看”。
我的個人博客地址:https://zwdnet.github.io
我的知乎文章地址: https://www.zhihu.com/people/zhao-you-min/posts
我的博客園博客地址: https://www.cnblogs.com/zwdnet/
我的微信個人訂閱號:趙瑜敏的口腔醫學學習園地


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM