Звучит легко, правда Нет. Постановка задачи является лишь верхушкой айсберга
Скачать 0.93 Mb.
|
KaggleТитаник — известная задача на Kaggle, ориентированная в большей мере на начинающих в машинном обучении. Датасет Титаник содержит данные пассажиров корабля. Цель задачи — построить модель, которая лучшим образом сможет предсказать, остался ли произвольный пассажир в живых или нет. Я разработчик программного обеспечения, ставший энтузиастом в анализе данных. Недавно я начал постигать тонкости Data Science. Когда я начал изучать видеокурсы на таких сайтах, как Udemy, Coursera и т.д., из-за одной задачи у меня пропало желание решать ее и другие задачи, и я стал больше слушать и меньше делать. У меня не было практики, хотя я понимал большую часть теории. В этот момент я наткнулся на Kaggle, сайт с набором задач в области Data Science и соревнованиями, проводимыми несколькими крупными технологическими компаниями, такими как Google. Во всем мире Kaggle известен своими интересными, сложными и очень захватывающими задачами. Одной из таких задач является датасет Титаник. Подводя итог, можно сказать, что задача Титаник основана на потоплении «непотопляемого» корабля «Титаник» в начале 1912 года. Она дает вам информацию о пассажирах, такую как их возраст, пол, число братьев и сестер, порт посадки и выжили ли они или нет в катастрофе. Основываясь на этой информации, вы должны предсказать, сможет ли произвольный пассажир на Титанике пережить затопление. Звучит легко, правда? Нет. Постановка задачи является лишь верхушкой айсберга. Используемые библиотекиPandas Seaborn Sklearn WordCloud Начальный этапНа начальном этапе рассматривались признаки полного датасета. Здесь я не пытался производить действия над признаками, а просто наблюдал их значения.1. Загрузка данных Я сразу загрузил данные из train и test датасетов. Полученный датасет имел 1309 строк и 12 столбцов. Каждая строка представляла уникального пассажира Титаника, а в каждом столбце содержались количественные или категориальные признаки для каждого пассажира. trd = pd.read_csv('train.csv') tsd = pd.read_csv('test.csv') td = pd.concat([trd, tsd], ignore_index=True, sort = False) 2. Пропущенные значения В датасете было несколько столбцов, в которых отсутствовали значения. Признак «Cabin» имел 1014 пропущенных значений. Столбец «Embarked», который отображал пункт посадки пассажиров, имел всего 2 пропущенных значения. В признаке «Age» было 263 пропущенных значения, а в столбце «Fare» — одно. td.isnull().sum() sns.heatmap(td.isnull(), cbar = False).set_title("Missing values heatmap") 3. Категориальные признаки Далее, чтобы определить категориальные признаки, я взглянул на количество уникальных значений в каждом столбце. Признаки «Sex» и «Survived» имели два возможных значения, а «Embarked» и «Pclass» имели три возможных значения. td.nunique() PassengerId 1309 Survived 2 Pclass 3 Name 1307 Sex 2 Age 98 SibSp 7 Parch 8 Ticket 929 Fare 281 Cabin 186 Embarked 3 dtype: int64ПризнакиПолучив лучшее представление о различных аспектах датасета, я начал исследовать признаки и роль, которую они сыграли в выживании или гибели путешественника.1. Survived Первый признак показывал, выжил ли пассажир или умер. Сравнение показало, что более 60% пассажиров умерли. 2. Pclass Этот признак показывает класс, которым следовал пассажир. Пассажиры могли выбрать из трех отдельных классов, а именно: класс 1, класс 2 и класс 3. Третий класс имел наибольшее количество пассажиров, затем класс 2 и класс 1. Количество пассажиров в третьем классе было больше, чем количество пассажиров в первом и втором классе вместе взятых. Вероятность выживания пассажира класса 1 была выше, чем пассажира класса 2 и класса 3. 3. Sex Примерно 65% пассажиров составляли мужчины, а остальные 35% — женщины. Тем не менее, процент выживших женщин был выше, чем число выживших мужчин. Более 80% мужчин умерли, в сравнении с примерно 70% женщинами. 4. Age Самому молодому путешественнику на борту было около двух месяцев, а самому старшему — 80 лет. Средний возраст пассажиров на борту был чуть менее 30 лет. Большая часть детей в возрасте до 10 лет выжила. В любой другой возрастной группе число жертв было выше, чем число выживших. Более 140 человек в возрастной группе 20-30 лет погибли в сравнении с примерно 80 выжившими того же возраста. 5. SibSp SibSp — это число братьев, сестер или супругов на борту у человека. Максимум 8 братьев и сестер путешествовали вместе с одним из путешественников. Более 90% людей путешествовали в одиночку или с одним из своих братьев и сестер или супругом(ой). Шансы на выживание резко падали, если кто-то ездил с более чем двумя родными. 7. Fare Разделив сумму тарифа на четыре категории, стало очевидно, что существует тесная связь между стоимостью тарифа и выживанием. Чем больше заплатит пассажир, тем выше будут его шансы на выживание. Я добавил новые категории тарифов в новый столбец Fare_Category. td['Fare_Category'] = pd.cut(td['Fare'], bins=[0,7.90,14.45,31.28,120], labels=['Low','Mid', 'High_Mid','High'])Заполнение пропущенных данных Существует множество процессов заполнения пропусков, которые можно использовать. Я использовал некоторые из них. 1. Embarked Поскольку у «Embarked» было только два пропущенных значения и наибольшее количество пассажиров отправлялось из Саутгемптона, вероятность посадки в Саутгемптоне выше. Итак, мы заполняем недостающие значения Саутгемптоном. Однако вместо того, чтобы вручную вводить Саутгемптон, мы найдем моду столбца Embarked и подставим в него отсутствующие значения. Мода — наиболее часто встречающийся элемент в выборке. td.Embarked.fillna(td.Embarked.mode()[0], inplace = True)2. Cabin В колонке «Cabin» было много пропущенных данных. Я решил определить все отсутствующие данные в отдельный класс. Я назвал его NA и заполнил все пропущенные значения этим значением. td.Cabin = td.Cabin.fillna('NA') 3. Age Возраст был самым непростым столбцом для заполнения. Возраст имел 263 пропущенных значения. Я сперва классифицировал людей на основе их имени. Разделение строк простого Python было достаточно, чтобы извлечь префикс для обращений (например, Mr, Miss, Mrs) из каждого имени. Было 18 разных названий. td['Salutation'] = td.Name.apply(lambda name: name.split(',')[1].split('.')[0].strip())Затем я сгруппировал эти названия по Sex и PClass. grp = td.groupby(['Sex', 'Pclass'])Медиана группы затем была подставлена в пропущенные строки. grp.Age.apply(lambda x: x.fillna(x.median())) td.Age.fillna(td.Age.median, inplace = True) Прогнозирование Это был случай задачи классификации, и я попытался сделать предсказания с помощью двух алгоритмов — Случайный лес и Гауссовский Наивный Байесовский классификатор. Я был удивлен результатами. Наивный классификатор работал плохо, а Случайный лес, напротив, делал предсказания с точностью более 80%. # Data to be predicted X_to_be_predicted = td[td.Survived.isnull()] X_to_be_predicted = X_to_be_predicted.drop(['Survived'], axis = 1) # X_to_be_predicted[X_to_be_predicted.Age.isnull()] # X_to_be_predicted.dropna(inplace = True) # 417 x 27 #Training data train_data = td train_data = train_data.dropna() feature_train = train_data['Survived'] label_train = train_data.drop(['Survived'], axis = 1) ##Gaussian clf = GaussianNB() x_train, x_test, y_train, y_test = train_test_split(label_train, feature_train, test_size=0.2) clf.fit(x_train, np.ravel(y_train)) print("NB Accuracy: "+repr(round(clf.score(x_test, y_test) * 100, 2)) + "%") result_rf=cross_val_score(clf,x_train,y_train,cv=10,scoring='accuracy') print('The cross validated score for Random forest is:',round(result_rf.mean()*100,2)) y_pred = cross_val_predict(clf,x_train,y_train,cv=10) sns.heatmap(confusion_matrix(y_train,y_pred),annot=True,fmt='3.0f',cmap="summer") plt.title('Confusion_matrix for NB', y=1.05, size=15) Заключение В научных задачах, будь то климатология или медицина, всегда присутствует дополнительная мотивация. Приятно осознавать, что твои усилия не пропадут зря и принесут обществу очевидную пользу. Я верю, что в будущем, в том числе благодаря технологиям искусственного интеллекта, мы научимся понимать природные явления лучше. |