文章来源: https://www.jianshu.com/p/091b7dc8f12a
这是一篇手把手教你使用 Python 实现机器学习算法,并在数值型数据和图像数据集上运行模型的入门教程,当你看完本文后,你应当可以开始你的机器学习之旅了!
本教程会采用下述两个库来实现机器学习算法:
此外,你还将学习到:
在本文会用到的机器学习算法包括:
开始本教程前,需要先确保安装了一下的 Python 库:
--upgrade
)安装命令如下,推荐采用虚拟环境(比如利用 anaconda 创建一个新的环境):
$ pip install numpy
$ pip install pillow
$ pip install --upgrade scikit-learn
$ pip install tensorflow # or tensorflow-gpu
$ pip install keras
$ pip install opencv-contrib-python
$ pip install --upgrade imutils
本教程会用到两个数据集来帮助更好的了解每个机器学习算法的性能。
第一个数据集是 Iris(鸢尾花) 数据集。这个数据集的地位,相当于你刚开始学习一门编程语言时,敲下的 “Hello,World!”
这个数据集是一个数值型的数据,如下图所示,其实就是一个表格数据,每一行代表一个样本,然后每一列就是不同的属性。这个数据集主要是收集了三种不同的鸢尾花的数据,分别为:
对应图中最后一列 Class label
,然后还有四种属性,分别是:
这个数据集可能是最简单的机器学习数据集之一了,通常是用于教导程序员和工程师的机器学习和模式识别基础的数据集。
对于该数据集,我们的目标就是根据给定的四个属性,训练一个机器学习模型来正确分类每个样本的类别。
需要注意的是,其中有一个类别和另外两个类别是线性可分的,但这两个类别之间却并非线性可分,所以我们需要采用一个非线性模型来对它们进行分类。当然了,在现实生活中,采用非线性模型的机器学习算法是非常常见的。
第二个数据集是一个三场景的图像数据集。这是帮助初学者学习如何处理图像数据,并且哪种算法在这两种数据集上性能最优。
下图是这个三场景数据集的部分图片例子,它包括森林、高速公路和海岸线三种场景,总共是 948 张图片,每个类别的具体图片数量如下:
这个三场景数据集是采样于一个八场景数据集中,作者是 Oliva 和 Torralba 的 2001 年的一篇论文,Modeling the shape of the scene: a holistic representation of the spatial envelope
无论什么时候实现机器学习算法,推荐采用如下流程来开始:
这个流程会随着你机器学习方面的经验的积累而改善和优化,但对于初学者,这是我建议入门机器学习时采用的流程。
所以,现在开始吧!第一步,就是评估我们的问题,问一下自己:
最后一个问题非常重要,随着你使用 Python 实现机器学习的次数的增加,你也会随之获得更多的经验。根据之前的经验,你可能知道有一种算法的性能还不错。
因此,接着就是准备数据,也就是数据预处理以及特征工程了。
一般来说,这一步,包括了从硬盘中载入数据,检查数据,然后决定是否需要做特征提取或者特征工程。
特征提取就是应用某种算法通过某种方式来量化数据的过程。比如,对于图像数据,我们可以采用计算直方图的方法来统计图像中像素强度的分布,通过这种方式,我们就得到描述图像颜色的特征。
而特征工程则是将原始输入数据转换成一个更好描述潜在问题的特征表示的过程。当然特征工程是一项更先进的技术,这里建议在对机器学习有了一定经验后再采用这种方法处理数据。
第三步,就是检查各种机器学习算法,也就是实现一系列机器学习算法,并应用在数据集上。
这里,你的工具箱应当包含以下几种不同类型的机器学习算法:
应当选择比较鲁棒(稳定)的一系列机器学习模型来评估问题,因为我们的目标就是判断哪种算法在当前问题的性能很好,而哪些算法很糟糕。
决定好要采用的模型后,接下来就是训练模型并在数据集上测试,观察每个模型在数据集上的性能结果。
在多次实验后,你可能就是有一种“第六感”,知道哪种算法更适用于哪种数据集。
比如,你会发现:
而以上的经验获得,当然就需要你多动手,多进行实战来深入了解不同的机器学习算法了!
接下来就开始敲代码来实现机器学习算法,并在上述两个数据集上进行测试。本教程的代码文件目录如下,包含四份代码文件和一个 3scenes
文件夹,该文件夹就是三场景数据集,而 Iris
数据集直接采用 scikit-learn
库载入即可。
├── 3scenes
│ ├── coast [360 entries]
│ ├── forest [328 entries]
│ └── highway [260 entries]
├── classify_iris.py
├── classify_images.py
├── nn_iris.py
└── basic_cnn.py
代码和数据集文件可以在公众号后台,也就是公众号会话界面回复 『py_ml』获取!
首先是实现 classify_iris.py
,这份代码是采用机器学习算法来对 Iris
数据集进行分类。
首先导入需要的库:
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import load_iris
import argparse
# 设置参数
ap = argparse.ArgumentParser()
ap.add_argument("-m", "--model", type=str, default="knn", help="type of python machine learning model to use")
args = vars(ap.parse_args())
# 定义一个保存模型的字典,根据 key 来选择加载哪个模型
models = {
"knn": KNeighborsClassifier(n_neighbors=1),
"naive_bayes": GaussianNB(),
"logit": LogisticRegression(solver="lbfgs", multi_class="auto"),
"svm": SVC(kernel="rbf", gamma="auto"),
"decision_tree": DecisionTreeClassifier(),
"random_forest": RandomForestClassifier(n_estimators=100),
"mlp": MLPClassifier()
}
可以看到在 sklearn
库中就集成了我们将要实现的几种机器学习算法的代码,包括:
我们直接调用 sklearn
中相应的函数来实现对应的算法即可,比如对于 knn
算法,直接调用 sklearn.neighbors
中的 KNeighborsClassifier()
即可,只需要设置参数 n_neighbors
,即最近邻的个数。
这里直接用一个 models
的字典来保存不同模型的初始化,然后根据参数 --model
来调用对应的模型,比如命令输入 python classify_irs.py --model knn
就是调用 knn
算法模型。
接着就是载入数据部分:
print("[INFO] loading data...")
dataset = load_iris()
(trainX, testX, trainY, testY) = train_test_split(dataset.data,
dataset.target, random_state=3, test_size=0.25)
这里直接调用 sklearn.datasets
中的 load_iris()
载入数据,然后采用 train_test_split
来划分训练集和数据集,这里是 75% 数据作为训练集,25% 作为测试集。
最后就是训练模型和预测部分:
# 训练模型
print("[INFO] using ‘{}‘ model".format(args["model"]))
model = models[args["model"]]
model.fit(trainX, trainY)
# 预测并输出一份分类结果报告
print("[INFO] evaluating")
predictions = model.predict(testX)
print(classification_report(testY, predictions, target_names=dataset.target_names))
完整版代码代码如下:
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import load_iris
import argparse
# 设置参数
ap = argparse.ArgumentParser()
ap.add_argument("-m", "--model", type=str, default="knn", help="type of python machine learning model to use")
args = vars(ap.parse_args())
# 定义一个保存模型的字典,根据 key 来选择加载哪个模型
models = {
"knn": KNeighborsClassifier(n_neighbors=1),
"naive_bayes": GaussianNB(),
"logit": LogisticRegression(solver="lbfgs", multi_class="auto"),
"svm": SVC(kernel="rbf", gamma="auto"),
"decision_tree": DecisionTreeClassifier(),
"random_forest": RandomForestClassifier(n_estimators=100),
"mlp": MLPClassifier()
}
# 载入 Iris 数据集,然后进行训练集和测试集的划分,75%数据作为训练集,其余25%作为测试集
print("[INFO] loading data...")
dataset = load_iris()
(trainX, testX, trainY, testY) = train_test_split(dataset.data, dataset.target, random_state=3, test_size=0.25)
# 训练模型
print("[INFO] using ‘{}‘ model".format(args["model"]))
model = models[args["model"]]
model.fit(trainX, trainY)
# 预测并输出一份分类结果报告
print("[INFO] evaluating")
predictions = model.predict(testX)
print(classification_report(testY, predictions, target_names=dataset.target_names))
接着就是采用三场景图像数据集的分类预测代码 classify_images.py
,跟 classify_iris.py
的代码其实是比较相似的,首先导入库部分,增加以下几行代码:
from sklearn.preprocessing import LabelEncoder
from PIL import Image
from imutils import paths
import numpy as np
import os
其中 LabelEncoder
是为了将标签从字符串编码为整型,然后其余几项都是处理图像相关。
对于图像数据,如果直接采用原始像素信息输入模型中,大部分的机器学习算法效果都很不理想,所以这里采用特征提取方法,主要是统计图像颜色通道的均值和标准差信息,总共是 RGB 3个通道,每个通道各计算均值和标准差,然后结合在一起,得到一个六维的特征,函数如下所示:
def extract_color_stats(image):
‘‘‘
将图片分成 RGB 三通道,然后分别计算每个通道的均值和标准差,然后返回
:param image:
:return:
‘‘‘
(R, G, B) = image.split()
features = [np.mean(R), np.mean(G), np.mean(B), np.std(R), np.std(G), np.std(B)]
return features
然后同样会定义一个 models
字典,代码一样,这里就不贴出来了,然后图像载入部分的代码如下:
# 加载数据并提取特征
print("[INFO] extracting image features...")
imagePaths = paths.list_images(args[‘dataset‘])
data = []
labels = []
# 循环遍历所有的图片数据
for imagePath in imagePaths:
# 加载图片,然后计算图片的颜色通道统计信息
image = Image.open(imagePath)
features = extract_color_stats(image)
data.append(features)
# 保存图片的标签信息
label = imagePath.split(os.path.sep)[-2]
labels.append(label)
# 对标签进行编码,从字符串变为整数类型
le = LabelEncoder()
labels = le.fit_transform(labels)
# 进行训练集和测试集的划分,75%数据作为训练集,其余25%作为测试集
(trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.25)
上述代码就完成从硬盘中加载图片的路径信息,然后依次遍历,读取图片,提取特征,提取标签信息,保存特征和标签信息,接着编码标签,然后就是划分训练集和测试集。
接着是相同的训练模型和预测的代码,同样没有任何改变,这里就不列举出来了。
完整版如下:
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from PIL import Image
from imutils import paths
import numpy as np
import argparse
import os
def extract_color_stats(image):
‘‘‘
将图片分成 RGB 三通道,然后分别计算每个通道的均值和标准差,然后返回
:param image:
:return:
‘‘‘
(R, G, B) = image.split()
features = [np.mean(R), np.mean(G), np.mean(B), np.std(R), np.std(G), np.std(B)]
return features
# 设置参数
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", type=str, default="3scenes",
help="path to directory containing the ‘3scenes‘ dataset")
ap.add_argument("-m", "--model", type=str, default="knn",
help="type of python machine learning model to use")
args = vars(ap.parse_args())
# 定义一个保存模型的字典,根据 key 来选择加载哪个模型
models = {
"knn": KNeighborsClassifier(n_neighbors=1),
"naive_bayes": GaussianNB(),
"logit": LogisticRegression(solver="lbfgs", multi_class="auto"),
"svm": SVC(kernel="rbf", gamma="auto"),
"decision_tree": DecisionTreeClassifier(),
"random_forest": RandomForestClassifier(n_estimators=100),
"mlp": MLPClassifier()
}
# 加载数据并提取特征
print("[INFO] extracting image features...")
imagePaths = paths.list_images(args[‘dataset‘])
data = []
labels = []
# 循环遍历所有的图片数据
for imagePath in imagePaths:
# 加载图片,然后计算图片的颜色通道统计信息
image = Image.open(imagePath)
features = extract_color_stats(image)
data.append(features)
# 保存图片的标签信息
label = imagePath.split(os.path.sep)[-2]
labels.append(label)
# 对标签进行编码,从字符串变为整数类型
le = LabelEncoder()
labels = le.fit_transform(labels)
# 进行训练集和测试集的划分,75%数据作为训练集,其余25%作为测试集
(trainX, testX, trainY, testY) = train_test_split(data, labels, random_state=3