import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
train = pd.read_csv("./dataset/train.csv")
train
train_survived = train[train['Survived'] == 0].shape[0]
train_not_survived = train[train['Survived'] == 1].shape[0]
plt.pie([train_survived, train_not_survived], labels=['Survived: ' + str(train_survived), 'Not Survived: ' + str(train_not_survived)])
plt.show()
There are three different values of this field in train data.
pd.DataFrame({ 'PClass': train.Pclass.unique()})
ax = plt.subplot()
ax.hist([train[train.Survived == 0].Pclass, train[train.Survived == 1].Pclass], label=['Not Survived', 'Survived'])
ax.legend()
ax.set_xlabel('Pclass')
plt.show()
It it pretty clear that people with Pclass = 1 have more possibility to survive. So we keep this feature Pclass.
First, vectorize the names.
from sklearn.feature_extraction.text import CountVectorizer
name_vectorizer = CountVectorizer()
X = name_vectorizer.fit_transform(train.Name)
We got a sort of words.
pd.DataFrame({ 'name': name_vectorizer.get_feature_names() })
And a matrix of features.
pd.DataFrame(X.toarray())
Use k-means to cluster these features.
from sklearn.cluster import KMeans
n_clusters = 500
name_cls = KMeans(n_clusters = n_clusters)
name_cls.fit(X)
train['Name-Feature'] = name_cls.predict(X)
ax = plt.subplot()
ax.bar(range(0, 100), [train[(train['Name-Feature'] == i) & (train['Survived'] == 1)].shape[0] / (train[train['Name-Feature'] == i].shape[0]) for i in range(0, 100)])
ax.set_ylabel('Suvived Rate')
ax.set_xlabel('Name-Feature')
plt.show()
At least we have a distribution of survied rate under different clusters. So we keep this generated field Name-Feature.
There are two kinds of values of field Sex in train data.
pd.DataFrame({ 'Sex': train.Sex.unique() })
Categorize the field Sex.
train.loc[train.Sex == 'male', 'Male'] = 1
train.loc[train.Sex == 'female', 'Male'] = 0
ax = plt.subplot()
ax.hist([train[train.Survived == 0].Male, train[train.Survived == 1].Male], label=['Not Survived', 'Survived'])
ax.legend()
ax.set_xlabel('Male')
plt.show()
It is pretty clear that females have more possibility to survive than males. So we keep this field Sex.
The fields Age of some train instances are missed.
pd.DataFrame({ 'Age': train.Age.unique() })
from sklearn.linear_model import LinearRegression
train_with_age = train[train.Age.notna()]
fig, axes = plt.subplots(2)
axes[0].hist([train_with_age[train_with_age.Survived == 0].Age, train_with_age[train_with_age.Survived == 1].Age], label=['Not Survived', 'Survived'])
axes[0].legend()
axes[0].set_xlabel('Age')
reg = LinearRegression()
reg.fit(np.array(train_with_age.Age).reshape(-1, 1), train_with_age.Survived)
X = np.arange(train_with_age.Age.min(), train_with_age.Age.max(), 0.1)
Y = reg.predict(X.reshape(-1, 1))
axes[1].plot(X, Y)
axes[1].set_xlabel('age')
axes[1].set_ylabel('survived')
plt.show()
reg.coef_
In general, with increasing age, the survived rate shows a downward trend. So we keep this field Age.
And for the missing value of Age, we choose to use field Pclass to predict for a suitable value.
from sklearn.linear_model import LinearRegression
train_with_age = train[train.Age.notna()]
fig, axes = plt.subplots(2)
axes[0].hist([
train_with_age[train_with_age.Pclass == 1].Age,
train_with_age[train_with_age.Pclass == 2].Age,
train_with_age[train_with_age.Pclass == 3].Age], label=['Pclass=1', 'Pclass=2', 'Pclass=3'])
axes[0].legend()
axes[0].set_xlabel('Age')
reg_age = LinearRegression()
reg_age.fit(np.array(train_with_age.Pclass).reshape(-1, 1), train_with_age.Age)
X = np.arange(train_with_age.Pclass.min(), train_with_age.Pclass.max(), 0.1)
Y = reg_age.predict(X.reshape(-1, 1))
axes[1].plot(X, Y)
axes[1].set_xlabel('Age')
axes[1].set_ylabel('Pclass')
plt.show()
if train[train.Age.isna()].shape[0] > 0:
train.loc[train.Age.isna(), 'Age'] = reg_age.predict(np.array(train[train.Age.isna()].Pclass).reshape(-1, 1)).tolist()
The field SibSp indicates the number of family members aboard the Titanic. Thre are 7 possible values of the field SibSp.
pd.DataFrame({ 'SibSp': train.SibSp.unique() })
from sklearn.linear_model import LinearRegression
fig, axes = plt.subplots(2)
axes[0].hist([
train[train.Survived == 0].SibSp,
train[train.Survived == 1].SibSp], label=['Not Survived', 'Survived'])
axes[0].legend()
axes[0].set_xlabel('SibSp')
reg = LinearRegression()
reg.fit(np.array(train.SibSp).reshape(-1, 1), train.Survived)
X = np.arange(train.SibSp.min(), train.SibSp.max(), 0.1)
Y = reg.predict(X.reshape(-1, 1))
axes[1].plot(X, Y)
axes[1].set_xlabel('SibSp')
axes[1].set_ylabel('Survived')
plt.show()
It seems that with increasing number of siblings, the survied rate is reduced. So we keep this field SibSp.
The field Parch indicates the number of parents or children aboard the Titanic. There are also 7 possible values of this field.
pd.DataFrame({ 'Parch': train.Parch.unique() })
from sklearn.linear_model import LinearRegression
fig, axes = plt.subplots(2)
axes[0].hist([
train[train.Survived == 0].Parch,
train[train.Survived == 1].Parch], label=['Not Survived', 'Survived'])
axes[0].legend()
axes[0].set_xlabel('Parch')
reg = LinearRegression()
reg.fit(np.array(train.Parch).reshape(-1, 1), train.Survived)
X = np.arange(train.Parch.min(), train.Parch.max(), 0.1)
Y = reg.predict(X.reshape(-1, 1))
axes[1].plot(X, Y)
axes[1].set_xlabel('Parch')
axes[1].set_ylabel('Survived Rate')
plt.show()
It seems that with increasing number of Parch, the survied rate is reduced. So we keep this field Parch.
The field Ticket is the ticket number.
pd.DataFrame({ 'Ticket': train.Ticket.unique() })
Vectorize this field and use k-means to generate a feature called Ticket-Feature.
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.cluster import KMeans
ticket_vectorizer = CountVectorizer()
X = ticket_vectorizer.fit_transform(train.Ticket)
n_clusters = 500
ticket_cls = KMeans(n_clusters = n_clusters)
ticket_cls.fit(X)
train['Ticket-Feature'] = ticket_cls.predict(X)
ax = plt.subplot()
ax.bar(range(0, 100), [train[(train['Ticket-Feature'] == i) & (train['Survived'] == 1)].shape[0] / (train[train['Ticket-Feature'] == i].shape[0]) for i in range(0, 100)])
ax.set_ylabel('Suvived Rate')
ax.set_xlabel('Ticket-Feature')
plt.show()
At least we have a distribution of survied rate under different clusters. So we keep this generated field Ticket-Feature.
fig, axes = plt.subplots(2)
axes[0].hist([
train[train.Survived == 0].Fare,
train[train.Survived == 1].Fare], label=['Not Survived', 'Survived'])
axes[0].set_xlabel('Fare')
reg = LinearRegression()
reg.fit(np.array(train.Fare).reshape(-1, 1), train.Survived)
X = np.arange(train.Fare.min(), train.Fare.max(), 0.1)
Y = reg.predict(X.reshape(-1, 1))
axes[1].plot(X, Y)
axes[1].set_xlabel('Parch')
axes[1].set_ylabel('Survived Rate')
plt.show()
Convert the field Cabin to A-Z, - and categorize.
for i in range(ord('A'), ord('Z') + 1):
train.loc[train.Cabin.notna() & train.Cabin.str.contains(chr(i)), 'Cabin'] = chr(i)
for i in range(ord('A'), ord('Z') + 1):
train.loc[train.Cabin == chr(i), 'Cabin'] = i - ord('A')
if train[train.Cabin.isna()].shape[0] > 0:
train.loc[train.Cabin.isna(), 'Cabin'] = -1
train
The field Embarked indicates the place people aboard the Titanic. Some of them are missed.
pd.DataFrame({ 'Embarked': train.Embarked.unique() })
t = train[train.notna()]
for label in train.Embarked.unique():
if not pd.isna(label):
plt.bar(label, t[(t.Survived == 0) & (t.Embarked == label)].shape[0], label = label + ' / Survived')
plt.bar(label, t[(t.Survived == 1) & (t.Embarked == label)].shape[0], label = label + ' / Not Survived')
plt.legend()
plt.show()
train.groupby('Embarked').count()
Since the value S is the most common one, we choose S to fill in missied values.
train.loc[train.Embarked.isna(), 'Embarked'] = 'S'
And also, categorize this field.
train.loc[train.Embarked == 'C', 'Embarked'] = 0
train.loc[train.Embarked == 'Q', 'Embarked'] = 1
train.loc[train.Embarked == 'S', 'Embarked'] = 2
Now, select choosen fields.
train_x = train[['Pclass', 'Name-Feature', 'Male', 'Age', 'SibSp', 'Parch', 'Ticket-Feature', 'Fare', 'Cabin', 'Embarked']]
train_x = (train_x - train_x.min()) / (train_x.max() - train_x.min())
train_y = train.Survived
train_x
test = pd.read_csv('./dataset/test.csv')
test
No missed values.
pd.DataFrame({ 'Pclass': test.Pclass.unique() })
Vectorize and cluster.
X = name_vectorizer.transform(test.Name)
test['Name-Feature'] = name_cls.predict(X)
No missed values.
pd.DataFrame({ 'Sex': test.Sex.unique() })
Categorize.
test.loc[test.Sex == 'male', 'Male'] = 1
test.loc[test.Sex == 'female', 'Male'] = 0
Use the field Pclass to predict missed values.
if test[test.Age.isna()].shape[0] > 0:
test.loc[test.Age.isna(), 'Age'] = reg_age.predict(np.array(test[test.Age.isna()].Pclass).reshape(-1, 1)).tolist()
pd.DataFrame({ 'SibSp': test.SibSp.unique() })
pd.DataFrame({ 'Parch': test.Parch.unique() })
Vectorize and cluster.
X = ticket_vectorizer.transform(test.Ticket)
test['Ticket-Feature'] = ticket_cls.predict(X)
Fill missed values with mean.
if test[test.Fare.isna()].shape[0] > 0:
test.loc[test.Fare.isna(), 'Fare'] = test.Fare.mean()
Convert the field Cabin to A-Z, - and categorize.
for i in range(ord('A'), ord('Z') + 1):
test.loc[test.Cabin.notna() & test.Cabin.str.contains(chr(i)), 'Cabin'] = chr(i)
for i in range(ord('A'), ord('Z') + 1):
test.loc[test.Cabin == chr(i), 'Cabin'] = i - ord('A')
if test[test.Cabin.isna()].shape[0] > 0:
test.loc[test.Cabin.isna(), 'Cabin'] = -1
No missed values.
test.groupby('Embarked').count()
Categorize.
test.loc[test.Embarked == 'C', 'Embarked'] = 0
test.loc[test.Embarked == 'Q', 'Embarked'] = 1
test.loc[test.Embarked == 'S', 'Embarked'] = 2
Select choosen fields only and normalize.
test_x = test[['Pclass', 'Name-Feature', 'Male', 'Age', 'SibSp', 'Parch', 'Ticket-Feature', 'Fare', 'Cabin', 'Embarked']]
test_x = (test_x - test_x.min()) / (test_x.max() - test_x.min())
test_x
Now, we compare the performance of Random Forest, Support Vector Machine and Multi-Layer Perceptron.
from sklearn.neural_network import MLPClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import plot_roc_curve
x1, x2, y1, y2 = train_test_split(train_x, train_y)
rfc = RandomForestClassifier()
svc = SVC()
mlp = MLPClassifier(max_iter=1000)
rfc.fit(x1, y1)
svc.fit(x1, y1)
mlp.fit(x1, y1)
ax = plt.gca()
plot_roc_curve(rfc, x2, y2, ax = ax)
plot_roc_curve(svc, x2, y2, ax = ax)
plot_roc_curve(mlp, x2, y2, ax = ax)
plt.show()
clf = RandomForestClassifier()
clf.fit(train_x, train_y)
test_y = clf.predict(test_x)
prediction = pd.DataFrame({ 'PassengerId': test.PassengerId, 'Survived': test_y })
prediction
prediction.to_csv("./dataset/submission.csv", index = False)