热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

机器学习笔记使用机器学习进行鸟类物种分类

科学家们已经确定,一种已知的鸟类应该分为3个不同且独立的物种。这些物种是该国特定地区的特有物种,必须尽可能精确地跟踪和估计它们的种群。因此,一个非营利性的保护协会承担了这项任务。他

一、问题概述

        科学家们已经确定,一种已知的鸟类应该分为 3 个不同且独立的物种。这些物种是该国特定地区的特有物种,必须尽可能精确地跟踪和估计它们的种群。

        因此,一个非营利性的保护协会承担了这项任务。他们需要能够根据现场官员在野外观察到的特征记录他们遇到的物种。

        使用某些遗传特征和位置数据,您能预测已观察到的鸟类种类吗?

        这是一个初学者级别的练习比赛,你的目标是根据属性或位置预测鸟类的种类。

Bird Species Classification Challenge | bitgrit bitgrit hosts data science competitions for all levels. Join in and compete in a range of competitions.

         下面来看看前五行training_set.csv

bill_depth bill_length wing_length location mass sex ID
14.3 48.2 210 loc_2 4600 0 284
14.4 48.4 203 loc_2 4625 0 101
18.4 NA 200 loc_3 3400 0 400
14.98211382 47.50487805 NA NA 4800 0 98
18.98211382 38.25930705 217.1869919 loc_3 5200 0 103

         training_set和training_target可以根据‘id’列关联。

        列的含义如下

species : 动物种类 (A, B, C) bill_length : 喙长 (mm) bill_depth : 喙深 (mm) wing_length : 翼长 (mm) mass : 体重 (g) location : 岛型 (Location 1, 2, 3 ) 性别 :动物性别(0:男性;1:女性;NA:未知)

三、编写代码

1、导入库

import pandas as pd # plotting import matplotlib import matplotlib.pyplot as plt import seaborn as sns matplotlib.rcParams['figure.dpi'] = 100 sns.set(rc={'figure.figsize':(11.7,8.27)}) sns.set() %matplotlib inline # ml from sklearn.metrics import ConfusionMatrixDisplay, classification_report from sklearn.model_selection import train_test_split from sklearn.impute import SimpleImputer from sklearn.preprocessing import LabelEncoder from sklearn.tree import DecisionTreeClassifier from sklearn import tree

2、处理缺失值的方法

def missing_vals(df): """prints out columns with perc of missing values""" missing = [ (df.columns[idx], perc) for idx, perc in enumerate(df.isna().mean() * 100) if perc > 0 ] if len(missing) == 0: return "no missing values" # sort desc by perc missing.sort(key=lambda x: x[1], reverse=True) print(f"There are a total of {len(missing)} variables with missing values\n") for tup in missing: print(str.ljust(f"{tup[0]:<20} => {round(tup[1], 3)}%", 1))

3、加载数据

        首先,我们使用 read_csv 函数加载训练和测试数据。

        我们还将 training_set.csv(包含特征)与 training_target.csv(包含目标变量)合并并形成训练数据。

train = pd.read_csv("dataset/training_set/training_set.csv") labels = pd.read_csv("dataset/training_set/training_target.csv") # join target variable to training set train = train.merge(labels, on="ID") test = pd.read_csv("dataset/test_set/test_set.csv")

target_cols = "species" num_cols = ["bill_depth", "bill_length", "wing_length", "mass"] cat_cols = ["location", "sex"] all_cols = num_cols + cat_cols + [target_cols] train = train[all_cols]

4、探索性数据分析Exploratory Data Analysis (EDA)

         这是我们研究数据趋势和模式的地方,包括数字和分类。

train.info()

        使用 info 函数,我们可以看到行数和数据类型。 

Int64Index: 435 entries, 0 to 434 Data columns (total 7 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 bill_depth 434 non-null float64 1 bill_length 295 non-null float64 2 wing_length 298 non-null float64 3 mass 433 non-null float64 4 location 405 non-null object 5 sex 379 non-null float64 6 species 435 non-null object dtypes: float64(5), object(2) memory usage: 27.2+ KB

        Numerical

        让我们绘制数值变量的直方图。 

train[num_cols].hist(figsize=(20, 14));

        bill_depth 在 15 和 19 左右达到峰值
        纸币长度在 39 和 47 左右达到峰值
        翼长在 190 和 216 左右达到峰值
        质量向右倾斜

        Categorical

to_plot = cat_cols + [target_cols] fig, axes = plt.subplots(1, 3, figsize=(20, 7), dpi=100) for i, col_name in enumerate(train[to_plot].columns): sns.countplot(x = col_name, data = train, palette="Set1", ax=axes[i % 3]) axes[i % 3].set_title(f"{col_name}", fOntsize=13) plt.subplots_adjust(hspace=0.45)

         我们看到位置和物种似乎与它们各自的位置和物种相匹配(loc2 和物种 C、loc3 和物种 A)。 我们还看到雌性 (1) 鸟类比雄性鸟类略多。

train.species.value_counts()

C 182 A 160 B 93 Name: species, dtype: int64

        仔细观察,我们发现目标变量是不平衡的,其中 B 类比 C 低近 100 个类,比 A 低大约 70 个。

        不平衡类是一个问题,因为它使模型偏向于更重视具有更多样本的类,即。 C 比 B 更经常被预测。

5、缺失数据

        缺失值的百分比

missing_vals(train)

There are a total of 6 variables with missing values bill_length => 32.184% wing_length => 31.494% sex => 12.874% location => 6.897% mass => 0.46% bill_depth => 0.23%

        通过我们的辅助函数,我们发现 bill_length 和wing_length 有超过 30% 的缺失值

        热图Heatplot

plt.figure(figsize=(10, 6)) sns.heatmap(train.isnull(), yticklabels=False, cmap='viridis', cbar=False);

         我们还可以绘制热图以可视化缺失值并查看是否有任何模式。

        估算分类列

        让我们先看看我们的分类变量中有多少缺失变量

train.sex.value_counts(dropna=False)

1.0 195 0.0 184 NaN 56 Name: sex, dtype: int64

train.location.value_counts(dropna=False)

loc_2 181 loc_3 141 loc_1 83 NaN 30 Name: location, dtype: int64

        让我们使用简单的 imputer 来处理它们,用最频繁的值替换它们。

cat_imp = SimpleImputer(strategy="most_frequent") train[cat_cols] = cat_imp.fit_transform(train[cat_cols])

        再次确认,已经没有缺失值了。如您所见,通过“最频繁”策略,缺失值被估算为 1.0,这是最频繁的。 

train.sex.value_counts(dropna=False)

1.0 251 0.0 184 Name: sex, dtype: int64

        估算数值列

        让我们使用中值来估算我们的数值

num_imp = SimpleImputer(strategy="median") train[num_cols] = num_imp.fit_transform(train[num_cols])

missing_vals(train)

'no missing values'

6、特征工程

train.species.value_counts()

C 182 A 160 B 93 Name: species, dtype: int64

        编码分类变量

        使用标签编码器,我们可以将分类变量(和目标变量)编码为数值。 我们这样做是因为大多数 ML 模型不适用于字符串值。

le = LabelEncoder() le.fit(train['species']) le_name_map = dict(zip(le.classes_, le.transform(le.classes_))) le_name_map

{'A': 0, 'B': 1, 'C': 2}

        我们可以先把编码器拟合到变量上,然后查看映射是什么样子的,这样以后我们就可以反转映射了

train['species'] = le.fit_transform(train['species'])

        对于其他具有字符串变量(非数字)的列,我们也进行相同的编码。

for col in cat_cols: if train[col].dtype == "object": train[col] = le.fit_transform(train[col])

train.head()

# Convert cat_features to pd.Categorical dtype for col in cat_cols: train[col] = pd.Categorical(train[col])

         我们还将分类特征转换为 pd.Categorical dtype

train.dtypes

bill_depth float64 bill_length float64 wing_length float64 mass float64 location category sex category species int64 dtype: object

7、创建新特征

train['b_depth_length_ratio'] = train['bill_depth'] / train['bill_length'] train['b_length_depth_ratio'] = train['bill_length'] / train['bill_depth'] train['w_length_mass_ratio'] = train['wing_length'] / train['mass']

        在这里,我们创建一些具有除法的特征以形成变量的比率

train.head()

8、模型

        训练测试拆分

        现在是构建模型的时候了,我们首先将其拆分为 X(特征)和 y(目标变量),然后将其拆分为训练集和评估集。

        训练是我们训练模型的地方,评估是我们在将模型拟合到测试集之前对其进行测试的地方。

X, y = train.drop(["species"], axis=1), train[["species"]].values.flatten() X_train, X_eval, y_train, y_eval = train_test_split( X, y, test_size=0.25, random_state=0)

        简单的决策树分类器

        在这里,我们使用 max_depth = 2 的简单超参数拟合基线模型

dtree_model = DecisionTreeClassifier(max_depth = 2).fit(X_train, y_train)

        拟合数据后,我们可以使用它来进行预测

dtree_pred = dtree_model.predict(X_eval)

9、模型性能

print(classification_report(dtree_pred, y_eval))

precision recall f1-score support 0 1.00 0.70 0.82 57 1 0.71 0.92 0.80 13 2 0.75 1.00 0.86 39 accuracy 0.83 109 macro avg 0.82 0.87 0.83 109 weighted avg 0.88 0.83 0.83 109

        分类报告向我们展示了分类器的有用指标。

        例如,我们模型的 f1-score 为 0.83

10、混淆矩阵

        我们还可以构建一个混淆矩阵来可视化我们的分类器在什么方面做得好/坏。

# save the target variable classes class_names = le_name_map.keys() titles_optiOns= [ ("Confusion matrix, without normalization", None), ("Normalized confusion matrix", "true"), ] for title, normalize in titles_options: fig, ax = plt.subplots(figsize=(8, 8)) disp = ConfusionMatrixDisplay.from_estimator( dtree_model, X_eval, y_eval, display_labels=class_names, cmap=plt.cm.Blues, normalize=normalize, ax = ax ) disp.ax_.set_title(title) disp.ax_.grid(False) print(title) print(disp.confusion_matrix)

Confusion matrix, without normalization [[40 0 0] [ 5 12 0] [12 1 39]] Normalized confusion matrix [[1. 0. 0. ] [0.29411765 0.70588235 0. ] [0.23076923 0.01923077 0.75 ]]

         混淆矩阵向我们展示了它预测了更多的 A 类和 C 类,这并不奇怪,因为我们有更多的样本。

        它还表明该模型在应该是 B/C 时预测了更多的 A 类。

11、特征重要性

feature_imp = pd.DataFrame(sorted(zip(dtree_model.feature_importances_,X.columns)), columns=['Value','Feature']) plt.figure(figsize=(20, 15)) sns.barplot(x="Value", y="Feature", data=feature_imp.sort_values(by="Value", ascending=False)) plt.title('LightGBM Features') plt.tight_layout() # plt.savefig('lightgbm_fimp.png')

        从特征重要性来看,似乎质量预测物种的能力最好,其次是喙长。 其他变量在分类器中的重要性似乎为零

fig = plt.figure(figsize=(25,20)) _ = tree.plot_tree(dtree_model, feature_names=X.columns, class_names=list(class_names), filled=True)

        我们看到了在我们的决策树分类器的可视化中如何使用特征重要性。

        在根节点中,如果质量低于 4600 左右,则检查 bill_length,否则检查 bill_depth,然后在叶处预测类别。

 四、预测测试数据

        现在是时候在我们将模型拟合到测试数据之前,对训练数据进行相同的特征预处理和工程了。

le = LabelEncoder() cat_imp = SimpleImputer(strategy="most_frequent") num_imp = SimpleImputer(strategy="median") test[cat_cols] = cat_imp.fit_transform(test[cat_cols]) test[num_cols] = num_imp.fit_transform(test[num_cols]) for col in cat_cols: if test[col].dtype == "object": test[col] = le.fit_transform(test[col]) # Convert cat_features to pd.Categorical dtype for col in cat_cols: test[col] = pd.Categorical(test[col]) # save ID column test_id = test["ID"] all_cols.remove('species') test = test[all_cols] test['b_depth_length_ratio'] = test['bill_depth'] / test['bill_length'] test['b_length_depth_ratio'] = test['bill_length'] / test['bill_depth'] test['w_length_mass_ratio'] = test['wing_length'] / test['mass']

test_preds = dtree_model.predict(test) submission_df = pd.concat([test_id, pd.DataFrame(test_preds, columns=['species'])], axis=1) submission_df.head()

ID species
0 2 2
1 5 0
2 7 0
3 8 0
4 9 0

        请注意,物种值是数字,我们必须将其转换回字符串值。 使用之前带有 fit 的标签编码器,我们可以这样做。

le_name_map

{'A': 0, 'B': 1, 'C': 2}

inv_map = {v: k for k, v in le_name_map.items()} inv_map

{0: 'A', 1: 'B', 2: 'C'}

submission_df['species'] = submission_df['species'].map(inv_map) submission_df.head()

ID species
0 2 C
1 5 A
2 7 A
3 8 A
4 9 A

submission_df.to_csv('solution.csv', index=False)

        最后,我们将数据框写入 csv 文件。


推荐阅读
  • 基于词向量计算文本相似度1.测试数据:链接:https:pan.baidu.coms1fXJjcujAmAwTfsuTg2CbWA提取码:f4vx2.实验代码:imp ... [详细]
  • 前言:拿到一个案例,去分析:它该是做分类还是做回归,哪部分该做分类,哪部分该做回归,哪部分该做优化,它们的目标值分别是什么。再挑影响因素,哪些和分类有关的影响因素,哪些和回归有关的 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 本文介绍了在Python张量流中使用make_merged_spec()方法合并设备规格对象的方法和语法,以及参数和返回值的说明,并提供了一个示例代码。 ... [详细]
  • 本文介绍了使用Spark实现低配版高斯朴素贝叶斯模型的原因和原理。随着数据量的增大,单机上运行高斯朴素贝叶斯模型会变得很慢,因此考虑使用Spark来加速运行。然而,Spark的MLlib并没有实现高斯朴素贝叶斯模型,因此需要自己动手实现。文章还介绍了朴素贝叶斯的原理和公式,并对具有多个特征和类别的模型进行了讨论。最后,作者总结了实现低配版高斯朴素贝叶斯模型的步骤。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 如何使用Python从工程图图像中提取底部的方法?
    本文介绍了使用Python从工程图图像中提取底部的方法。首先将输入图片转换为灰度图像,并进行高斯模糊和阈值处理。然后通过填充潜在的轮廓以及使用轮廓逼近和矩形核进行过滤,去除非矩形轮廓。最后通过查找轮廓并使用轮廓近似、宽高比和轮廓区域进行过滤,隔离所需的底部轮廓,并使用Numpy切片提取底部模板部分。 ... [详细]
  • HashMap的扩容知识详解
    本文详细介绍了HashMap的扩容知识,包括扩容的概述、扩容条件以及1.7版本中的扩容方法。通过学习本文,读者可以全面了解HashMap的扩容机制,提升对HashMap的理解和应用能力。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
  • pythonMatplotlib(二)
    Matplotlib+pandas作图一、对csv文件进行提取ruixi.csv对上述表格进行提取并做图画出图像二、对.xlsx进行提取:rui ... [详细]
  • 动量|收益率_基于MT策略的实战分析
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了基于MT策略的实战分析相关的知识,希望对你有一定的参考价值。基于MT策略的实战分析 ... [详细]
  • 数学建模入门python绘制频率直方图
    文章目录例题数据处理绘图操作调用演示例题数据处理将以下的数据保存到磁盘上17275169551696417165167471716216867165521696216865 ... [详细]
  • plt python 画直线_机器学习干货,一步一步通过Python实现梯度下降的学习
    GradientDescent-梯度下降梯度下降法(英语:Gradientdescent)是一个一阶最优化算法,通常也称为最速下降法。要使用梯度下降法找 ... [详细]
author-avatar
single
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有