机器学习基础知识总结(期末复习)

目录

一、机器学习概述

二、机器学习工具的安装与使用

三、线性模型

四、决策树和随机森林

五、支持向量机

六、朴素贝叶斯

七、K最近邻算法

八、神经网路

一、机器学习概述

 机器学习是人工智能的一个子领域,人工智能所包含的范围更广,例如,知识图谱也是人工智能的一个子领域。机器学习是在1952年由亚瑟赛缪尔提出来的,机器学习最早应用出现在1960年。

学习机器学习需要掌握一门编程语言,这里推荐使用python,python语言语法简洁,且python拥有一个庞大的机器学习库。

学习机器学习要提前了解数据集和数据集预处理等概念,以及对模型的掌握。

机器学习的苏纳法主要有两种:监督学习(supervised learning)和无监督学习(unsupervised learning),除此之外还有半监督学习,不过不在此处过多介绍。

监督学习是通过现有训练数据集进行建模,在用模型对新的数据样本进行分类或者回归分析的机器学习算法。

无监督学习,则是在没有训练集的情况下,对标签的数据进行分析并建立合适的模型,以便给出问题解决方案的方法。

分类(classfication)和回归(regression)都是监督学习中的概念,分类预测样本属于哪个类别,而回归预测样本目标字段的数值。

数据集(dataset)是预测系统的原材料,用于训练机器学习模型的历史数据。数据集由诺干条数据组成,而每条数据又包含诺干个特征(feature)。

特征工程是创建预测模型之前的过程,在这个过程中我们将对数据的特征进行分析、清理和结构化。

过拟合,顾名思义就是模型算法对训练数据拟合的太“好”了,具体来说就是训练集准确率远高于验证集准确率,此时就会发生过拟合,相反,则会发生欠拟合。

二、机器学习工具的安装与使用

Anaconda是一个开源软件包集合平台,也是一个环境管理器,它可以在同一个机器上安装多个不同版本的软件包及依赖项,并且能够在不同环境进行切换。

Anaconda 下载,首先进入Anaconda官网https://www.anaconda.com/

 点击左上角的freeDownload

 如果使用windows直接点击Download,如果使用的是mac或者Linux,点击相应的图标下载即可。

下载完成后点击下图的Anaconda Navigator启动Anaconda

 启动之后

点击Launch启动

点击new,选择python3,新建jupyter记事本

以后的代码均在jupyter记事本中书写

pandas软件包是python开源的包,主要用于数据处理和数据分析。

使用pandas读取csv文件

import pandas as pd
datasets = pd.read_csv('../fashion_数据集/fashion-mnist_train.csv')
datasets.head()

显示数据集的结果

 pandas的其他函数应用

datasets.info()#查看数据集的描述信息
datasets.describe() #查看数据集的数据统计信息

可视化工具seaborn基于Matplotlib的图形可视化包,下面我们使用seaborn绘制一个直方图

import matplotlib.pyplot as plt
import seaborn as sns
sns.displot(data['age'])
plt.show()

 显示结果

 scikit-learn(以下简称sklearn)机器学习库内置很多标准数据集和机器学习算法,封装了许多机器学习算法,包括分类、回归、聚类、数据降维等。

sklearn库包含数据集有很多,其中 比较典型的有load_digits(手写数字识别),load_iris(鸢尾花),load_breast_cancer (乳腺癌),load_diabetes (糖尿病),load_boston (波士顿房屋)等。

这里我们以手写数字识别为例,导入数据集,查看数据集中的键名

from sklearn import datasets
digits = datasets.load_digits()
digits.keys()

运行结果显示

 该数据集以字典类型存储

接下来,我们对sklearn库中的模型进行训练评估,这里我们先导入数据集拆分工具train_test_split

from sklearn.model_selection import train_test_split
x = digits.data
y = digits.target
x.shape,y.shape

将数据集中的样本和标签分别赋值给x和y,并查看其形状

输出结果显示

然后使用train_test_split拆分为训练集和验证集,随机种子设置为42

x_train,x_test,y_train,y_test = train_test_split(x,y,random_state=42)

接下来,我们开始导入sklearn库中的第一个模型svm(支持向量机),对模型进行训练

from sklearn import svm
clf = svm.SVC()
clf.fit(x_train,y_train)

fit函数用于训练

输出结果显示

输出SVC()表示已经训练完成

然后对模型进行评估

clf.score(x_test,y_test)

 输出结果显示

从运行结果可以看出,我们训练的第一个模型准确率拥有98.6%的准确率。

三、线性模型

线性模型指一类算法,在机器学习中,线性模型包括线性回归、岭回归、套索回归、逻辑回归、线性支持向量机等。

线性模型的基本公式:

为了更好的理解什么是线性模型,我们可以假设数据集中样本都只有 一个特征,公式如下:

 

 这个公式实际上就是一个直线方程,w为权重-2,b为偏差3,此时的方程可以写为:

 下面使用图形的方式来绘制这个方程所对应的直线

import numpy as np
import matplotlib.pyplot as plt
#生成一个-10到10的元素数为200的等差数列
x = np.linspace(-10,10,200)
#输入直线方程
y = -2*x+3
#绘制折线图
plt.plot(x,y,c='purple')
#折线图标题
plt.title('basic Linear model')
#显示图形
plt.show()

输出结果显示

 接下来,我们开始介绍线性回归模型的使用

首先,我们使用pandas库生成一个简单的数据集

#导入pandas
import pandas as pd
#设置 数据集
data = {'Age':[14,18,20],'Height':[165,175,178]}
data_frame = pd.DataFrame(data)
data_frame.head()

输出结果显示

导入线性回归模型

from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as plt
#把样本的年龄赋值给x
x = data_frame['Age'].values.reshape(-1,1)
#把样本的身高数据赋值给y2
y = data_frame['Height']
model = LinearRegression()
model.fit(x,y)
z = np.linspace(10,20,20)
print("模型准确率:",model.score(x,y))
plt.scatter(x,y ,s =80)
plt.plot(z,model.predict(z.reshape(-1,1)))
plt.title('Age and Height')
plt.show()

输出结果显示

通过运行结果我们可以发现,模型准确率高达98.7%,且线性回归拟合了三名学生的身高和年龄数据。从此我们可以得出结论:两点确定一条直线,该直线便是线性回归算法训练的模型。

下面我们开始介绍岭回归的使用及原理,上文中说到模型在训练时由于各种原因容易发生过拟合和欠拟合的问题,岭回归使用L2正则化的方法防止模型发生过拟合。

我们继续使用线性回归模型制作的身高年龄数据集

导入岭回归模型


#%%
from sklearn.linear_model import Ridge
import numpy as np
import matplotlib.pyplot as plt
#把样本的年龄赋值给x
x = data_frame['Age'].values.reshape(-1,1)
#把样本的身高数据赋值给y2
y = data_frame['Height']
model = Ridge()
model.fit(x,y)
z = np.linspace(10,20,20)
plt.scatter(x,y ,s =80)
plt.plot(z,model.predict(z.reshape(-1,1)),c='k')
plt.title('Age and Height')
plt.show()

在使用默认参数情况下,岭回归生成的模型看=看起来与线性回归模型非常接近。

下面我们使用alpha参数进行模型调整

model = Ridge(alpha=20)

我们在岭回归模型中加入了alpha参数,并赋值为20,此时运行查结果

此时,3个样本点距离更远了,直线也变得平缓了,这说明模型对训练集的拟合度降低了,通过这种方法可以有效避免过拟合。

下面我们介绍套索回归,套索回归使用L1正则化将某些特征的权重等于0,摒除掉该特征。

下面我们使用糖尿病数据集‘

导入相关的库和工具’

import pandas as pd
#导入套索回归模型
from sklearn.linear_model import Lasso
#导入糖尿病数据集
from sklearn.datasets import load_diabetes
#导入数据集拆分工具
from sklearn.model_selection import train_test_split
#导入可视化库
import matplotlib.pyplot as plt
#定义一个datasets变量保存糖尿病数据集
datasets = load_diabetes()

进行模型训练,查看训练集与测试集的准确率

#将样本特征赋值给两个变量x,y
x,y = datasets.data,datasets.target
#将数据集拆分为训练集和验证集
x_trian,x_test,y_train,y_test = train_test_split(x,y,random_state=8,train_size=0.7)
#进行训练
lasso = Lasso(alpha=0.1)
lasso.fit(x_trian,y_train)
#查看训练集与测试集的准确率
print(lasso.score(x_trian,y_train))
print(lasso.score(x_test, y_test))

输出结果显示

从运行结果可以看出,在alpha=01的情况下,训练集为0.52,测试集为0.47,训练集准确率稍微高,这说明出现了轻微的过拟合。

接下来,我们通过调节alpha参数,对模型进行评估

lasso1 = Lasso(alpha=1)
lasso1.fit(x_trian,y_train)
lasso2 = Lasso(alpha=0.1)
lasso2.fit(x_trian,y_train)
lasso3 = Lasso(alpha=0.01)
lasso3.fit(x_trian,y_train)
#绘制a值等于1时的模型系数
plt.plot(lasso1.coef_,'s',label = "Lasso alpha = 1")
#绘制a值等于0.1时的模型系数
plt.plot(lasso2.coef_,'^',label = "Lasso alpha = 0.1")
#绘制a值等于0.01时的模型系数
plt.plot(lasso3.coef_,'v',label = "Lasso alpha = 0.01")
plt.hlines(0,0,len(lasso.coef_))
plt.legend(ncol = 2,loc = (0,1.05))
plt.xlabel("coefficient index")
plt.ylabel("coefficient magnitude")
plt.show()

输出结果显示

从图中我们可以看出,alpha参数等于0.01时,所有特征权重都不为0,这说明数据集样本特征都被模型使用了,这时模型的复杂度最高,也容易出现过拟合。

下面我们开始介绍逻辑回归和线性支持向量机,前面介绍的线性回归,岭回归,套索回归都是做回归任务,逻辑回归和线性支持向量机用于分类任务。

我们使用学生年龄身高数据制作一个简单的数据集

#导入pandas库
import pandas as pd
#制作一个带身高标签的数据集
data = {'Age':[14,16,18],'Height':[165,163,175],'is_tall':[1,0,1]}
#转化为pandas数据框
data_frame = pd.DataFrame(data)
#检查是否成功
data_frame.head()

输出结果显示

 下面导入逻辑回归模型

#导入逻辑回归模型
from sklearn.linear_model import LogisticRegression
#创建一个分类器
classfication = LogisticRegression()
#定义一个x和y
#x表示样本特征,只包含Age和Height两列,不包含is_tall,因此需要使用drop函数将is_tall删除掉,axis= 1代表删除列,axis=0代表删除行
x = data_frame.drop('is_tall',axis=1)
#y是数据集的标签列is_tall
y = data['is_tall']
classfication.fit(x,y)

输出结果显示

假设现在有第四名学生,年龄19岁,身高176cm,我们进行预测

student4 = [[19,176]]
classfication.predict(student4)

 输出结果显示

运行结果显示逻辑回归模型把第四名学生放在分类1,说明模型认为该同学属于身高较高的学生。

同样,我们可以使用线性支持向量机来进行预测

#导入线性支持向量机
from sklearn.svm import LinearSVC
#使用线性支持向量机创建分类器
svc = LinearSVC()
#拟合数据
svc.fit(x,y)
svc.predict(student4)

输出结果显示

显然,支持向量机对第四名同学的预测也是“1”。

四、决策树和随机森林

决策树算法是一种历史悠久的算法,原理十分简单,即通过对样本特征进行一系列判断,进而做出决策,举个例子,你听说长辈家的孩子要过生日了,打算送个礼物祝贺,具体送什么礼物,此时需要进行决策。

决策思维过程呈现出树状结构,所以这也是决策树名字的由来。

下面我们使用决策树模型进行决策

首先使用padans库进行制作数据集

#决策树模型
#导入相关库
import pandas as pd
from sklearn import tree
#制作一个数据集
#性别:0代表女,1代表男
#化妆:0代表否,1代表是
#打游戏:0代表否,1代表是
#’礼物‘列,代表最后分类的标签
data = {'性别':[0,0,1,1],'化妆':[1,0,0,0],'打游戏':[0,0,1,0],'礼物':['口红','包包','Xbox','限量版球鞋']}
#使用pandas库中的data_frame函数将数据转化为数据框
data_frame = pd.DataFrame(data)
#查看是否转化成狗
data_frame.head()

输出结果显示

 下面导入决策树模型

#数据集中,x代表特征,y代表标签,'礼物'列为标签,使用drop函数去除标签列,axis=1为去除列
x = data_frame.drop('礼物',axis=1)

y = data_frame['礼物']

#创建一个分类器
clf = tree.DecisionTreeClassifier()
#训练模型
clf.fit(x,y)

预测模型

#预测模型
#定义一个孩子特征
test = [0,1,0]
#使用训练好的模型进行预测
pre = clf.predict([test])
#输出
print(pre)

输出结果显示

结果显示,决策树模型根据我们输入孩子的特征,给出选择礼物的建议。

决策树模型中参数max_depth参数,这个参数用来设置决策树最大层数。

下面我们对max_depth参数进行探索

首先我们使用sklearn库内置的生成数据集的工具来生成数据集

#决策树中的max_depth参数
#导入相关库
from sklearn.datasets import make_blobs
from sklearn import tree
#定义一个变量用于接收make_blobs
model = make_blobs
#使用make_bl obs生成数据
#n_samples代表生成数据集的样本数量
#centers代表生成数据集分为多少类
#n_features代表生成的数据集样本的特征数量
x,y = model(n_samples = 200,centers = 3,n_features = 2)
print(x.shape)

对生成的数据集进行可视化

#导入可视化库
import matplotlib.pyplot as plt
#设置图形的宽和高
plt.figure(figsize=(9,6))
#绘制散点图
#x[:,0]代表所有样本的第一个特征
#x[:,1]代表所有样本的第二个特征
#c=y代表使用颜色区分样本的不同标签
#edgecolors设置的散点的边缘色,k代表黑色
#s=80代表设置散点的大小为80,
plt.scatter(x[:,0],x[:,1],c=y,cmap='autumn',edgecolors='k',s=80)
#显示图形
plt.show()

输出结果显示

接下来,我们设置不同的max_depth参数值来观看变化

max_depth=2时

import numpy as np
#创建一个max_depth分类器
classfication = tree.DecisionTreeClassifier(max_depth=2)
classfication.fit(x,y)
#首先设置图形的横纵坐标范围
x_min,x_max = x[:,0].min() -1,x[:,0].max() +1
y_min,y_max = x[:,1].min() -1,x[:,1].max() +1
#然后使用numpy的meshgrid()方法生成一个布满空间的网格
xx,yy = np.meshgrid(np.arange(x_min,x_max,0.02),np.arange(y_min,y_max,0.02))
#使用max_depth为1的分类器对网格中的所有数据进行预测
z = classfication.predict(np.c_[xx.ravel(),yy.ravel()])
#让z的形态和xx保持一致
z = z.reshape(xx.shape)
#创建大小为9x6的画布
plt.figure(figsize=(9,6))
plt.pcolormesh(xx,yy,z,cmap='summer')
plt.scatter(x[:,0],x[:,1],c = y,cmap='autumn',edgecolors = 'k',s = 80)
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(),yy.max())
plt.title("Tree:(max_depth = 3)")
plt.show()

输出结果显示

max_depth = 5

#创建一个max_depth分类器
classfication = tree.DecisionTreeClassifier(max_depth=5)
classfication.fit(x,y)
#首先设置图形的横纵坐标范围
x_min,x_max = x[:,0].min() -1,x[:,0].max() +1
y_min,y_max = x[:,1].min() -1,x[:,1].max() +1
#然后使用numpy的meshgrid()方法生成一个布满空间的网格
xx,yy = np.meshgrid(np.arange(x_min,x_max,0.02),np.arange(y_min,y_max,0.02))
#使用max_depth为1的分类器对网格中的所有数据进行预测
z = classfication.predict(np.c_[xx.ravel(),yy.ravel()])
#让z的形态和xx保持一致
z = z.reshape(xx.shape)
#创建大小为9x6的画布
plt.figure(figsize=(9,6))
plt.pcolormesh(xx,yy,z,cmap='summer')
plt.scatter(x[:,0],x[:,1],c = y,cmap='autumn',edgecolors = 'k',s = 80)
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(),yy.max())
plt.title("Tree:(max_depth = 5)")
plt.show()

输出结果显示

决策树优势与不足:

决策树在训练过程中对每个特征的处理都是相互独立的,这就不会对数据预处理有苛刻的要求,这也是决策树的一个优势。

决策树算法容易出现过拟合问题。

下面我们开始介绍随机森林算法

随机算法中的参数:

bootstrap参数指的是bootstrap sample ,也就是有放回的随机抽样,也被成为“自展法”。

max_features参数的值越高,随机森林中的每颗决策树的相似度越高,相反,则越低。

n_estimators参数控制的是随机森林中决策树的数量,决策树数量越多,随机森林结果准确率也越高,训练也更长,相反,数量越少,训练时间越短,结果准确率可能下降。

首先,前往ucl机器学习库下载一个名为Heart Disease UCI的数据集,使用pandas库中的read_csv函数读取该数据集。

#导入pandas库
import pandas as np
#读取心脏病数据集
data_frame = np.read_csv('../heart数据集/heart.csv')
#查看数据集的数据框
data_frame.head()

输出结果显示

接下来,我们使用该数据训练一个决策树模型

#导入决策树模型和数据集划分工具
from sklearn import tree
from sklearn.model_selection import train_test_split
#定义一个决策树模型
model = tree.DecisionTreeClassifier()
#将特征和标签赋值给x和y
x = data_frame.drop('target',axis=1)   #使用drop函数删除掉标签列,axis=1代表删除列
y = data_frame['target']
#将特征和标签拆分为训练集和验证集
x_train,x_test,y_train,y_test = train_test_split(x,y,train_size=0.7,random_state=42)
#训练模型
model.fit(x_train,y_train)
#评估模型的准确率
print("训练集的准确率:",model.score(x_train,y_train))
print("测试集的准确率:",model.score(x_test,y_test))

输出结果显示

从运行结果来看,模型出现了轻微的过拟合。

接下来,我们使用随机森林来进行试验,我们使用一个for循环来寻找一个最佳的n_estimators参数。

#导入随机森林
from sklearn.ensemble import RandomForestClassifier
#导入可视化库
import matplotlib.pyplot as plt
#创建一个空列表,用于存储模型的准确率
score_list = []
#创建一个10-100,步长为10的循环
for i in range(10,100,10):
    #让随机森林的n_estimators参数以10为单位,10-100遍历
    R_model =  RandomForestClassifier(n_estimators=i,random_state=0)
    #用不同参数的随机森林拟合训练集
    R_model.fit(x_train,y_train)
    #将模型在验证集中的准确率逐一添加到先前创建好的空列表中
    score_list.append(R_model.score(x_test,y_test))
plt.plot(range(10,100,10),score_list)
#中文乱码
plt.rcParams["font.sans-serif"]=["SimHei"] #设置字体
plt.rcParams["axes.unicode_minus"]=False
#标题
plt.title('不同n_estimators参数对应的模型准确率')
plt.show()

输出结果显示

从图中可以看出,当n_estimators参数达到18左右时,模型表现达到最佳。

用此方法,我们也可以探索max_depth参数的最佳值

#对决策树模型进行评估,寻找最优参数max_depth
tree_score_list = []
for i in range(1,10,1):
    model = tree.DecisionTreeClassifier(max_depth=i,random_state=0)
    model.fit(x_train,y_train)
    tree_score_list.append(model.score(x_test,y_test))
plt.plot(range(1,10,1),tree_score_list)
#中文乱码
plt.rcParams["font.sans-serif"]=["SimHei"] #设置字体
plt.rcParams["axes.unicode_minus"]=False
#标题
plt.title('不同max_depth参数对应的模型准确率')
plt.show()

输出结果显示

从图中可以看出,当max_depth参数达到3时,模型表现最佳。

五、支持向量机

 支持向量机(SVlM)又称支持向量网络,是在分类与回归分析中分析数据的监督学习算法。

在上文中,我们已经介绍过线性支持向量机,本节重点研究内核化支持向量机。

通过图形化帮助大家理解。

使用matplotlib可视化

#导入库
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np
#使用make_blobs生成试验数据
x,y = make_blobs(n_samples=100,n_features=3,random_state=5,)
y = y%3
#使用散点图来展示线性不可分数据
plt.scatter(x[:,0],x[:,1],c=y,s=80,cmap='autumn',edgecolors='k')
plt.show()

输出结果显示

通过观察该图,发现数据是一个非线性数据,因为该数据无法用一条直线分隔开,这种数据集是线性不可分数据集。

在这种情况下,我们可以给样本增加特征,并将数据投射到三维空间

from mpl_toolkits.mplot3d import Axes3D,axes3d
#创建一个绘图区域
figure = plt.figure()
#把x第2个特征的平方作为第3个特征,添加到原始数据中
x_new = np.hstack([x,x[:,1:]**2])
ax = Axes3D(figure,elev=-152,azim=26)
mask=y==0
ax.scatter(x_new[mask,0],x_new[mask,1],x_new[mask,2],c='r',s=80)
ax.scatter(x_new[~mask,0],x_new[~mask,1],x_new[~mask,2],c='b',marker='^',s=80)
plt.show()

输出结果显示

 当数据从二维变为三维后,数据就可以被一条直线分隔开。

支持向量机有多种内核,一种是多项式内核(polynomial kernel),另一种是径向基内核(RBF),上边讲到的就是多项式内核,下面进行介绍RBF内核。

RBF内核会对原始数据中的样本之间的距离进行重新计算,公式如下:

x1x2代表数据集中的两个样本,kBRF(x1,x2)代表对于RBF内核来说,x1,x2的距离

exp代表以e为底的指数函数,||x1-x2||指的是x1和x2之间欧几里得距离,Y指的是RBF内核中用来控制内核宽度的函数。

不同内核的支持向量机对比,我们使用鸢尾花数据集来进行试验

#导入鸢尾花数据集
from sklearn.datasets import load_iris
#导入支持向量机
from sklearn import svm
#导入相关库
import numpy as np
import matplotlib.pyplot as plt

#定义一个函数用来生成填满空间的网格
def make_meshgrid(x,y,h=.02):
    x_min,x_max = x.min() -1,x.max() +1
    y_min,y_max = y.min() -1,y.max() +1
    xx,yy = np.meshgrid(np.arange(x_min,x_max,h),np.arange(y_min,y_max
                                                           ,h))
    return xx,yy
#定义一个绘制等高线的函数
def plot_contours(ax,clf,xx,yy,**params):
    z = clf.predict(np.c_[xx.ravel(),yy.ravel()])
    z = z.reshape(xx.shape)
    out = ax.contourf(xx,yy,z,**params)
    return out

#使用鸢尾花数据集
iris = load_iris()
#只选取数据集的前两个特征,便于可视化
x = iris.data[:,:2]
y = iris.target
#固定svm的正则化参数
C = 1
#创建使用不同的内核支持向量机模型拟合数据
models = (svm.SVC(kernel='rbf',gamma=0.5,C=C),
          svm.SVC(kernel='rbf',gamma=5,C=C),
          svm.SVC(kernel='rbf',gamma=50,C=C))
models = (clf.fit(x,y) for clf in models)
#数据可视化
titles = ('SVC with linear kernel(gamma=0.5)','SVC with linear kernel(gamma=5)','SVC with linear kernel(gamma=50)')
fig,sub = plt.subplots(1,3,figsize = (12,3))
plt.subplots_adjust(wspace=0.4,hspace=0.2)
x0,x1 = x[:,0],x[:,1]
xx,yy = make_meshgrid(x0,x1)
for clf,title,ax in zip(models,titles,sub.flatten()):
    plot_contours(ax,clf,xx,yy,cmap = plt.cm.autumn,alpha=0.8)
    ax.scatter(x0,x1,c=y,cmap=plt.cm.plasma,s=40,edgecolors='k')
    ax.set_xlim(xx.min(),xx.max())
    ax.set_ylim(yy.min(),yy.max())
    ax.set_xlabel('Feature 0')
    ax.set_ylabel('Feature 1')
    ax.set_xticks(())
    ax.set_yticks(())
    ax.set_title(title)

输出结果显示

我们采用控制变量法,让kernal与C固定,来探索不同gamma参数对模型的影响,通过上图可以看出,越大gamma值,模型越复杂,越容易出现过拟合。

我们也使用同样的方法来对其他两个参数进行探索,由于代码一样,这里就不再给出相应代码,直接得出结论:线性内核生成的基本和线性模型一致,RBF内核是以曲线将不同的标签样本圈起来形成决定边界,而使用多项式生成的边界像是高函数曲线。C参数数值越大,模型就越复杂,模型越容易出现过拟合。

六、朴素贝叶斯

 朴素贝叶斯算法是一组基于贝叶斯定理的监督学习算法。

下面我们给出一个实例来演示朴素贝叶斯的使用

使用pandas库手动制作一个数据集

#伯努利朴素贝叶斯
import pandas as pd
data = {'年份':[2014,2015,2016,2017,2018],
        'M2同比增长超过10%':[1,1,1,0,0],
        '土地供应量增加超过10%':[0,0,0,1,1],
        '人口是否净流入':[1,1,1,0,0],
        '次年房价是否大幅上涨':[0,1,1,0,0]}
data_frame = pd.DataFrame(data)
data_frame.head()

 输出结果显示

导入伯努利朴素贝叶斯

#导入伯努利朴素贝叶斯
from sklearn.naive_bayes import BernoulliNB
#将样本特征和标签分别赋值给x,y
x = data_frame.drop(['年份','次年房价是否大幅上涨'],axis=1)
y = data_frame['次年房价是否大幅上涨']
#定义一个model用于存储伯努利朴素贝叶斯模型
model = BernoulliNB()
#模型训练
model.fit(x,y)
model.score(x,y)

 输出结果显示

使用伯努利朴素贝叶斯进行预测

#使用伯努利朴素贝叶斯进行模型预测
x_predict_2019 = [[0,1,0]]
y_predict_2019 = model.predict(x_predict_2019)
#输出预测结果
print('预测的结果:',y_predict_2019)
if y_predict_2019 == 0:
    print('次年房价不会大幅度上涨')
elif y_predict_2019 == 1:
    print('次年房价会大幅度上涨')
else:
    print('无效的结果')

输出结果显示

下面导入高斯朴素贝叶斯模型进行预测

#导入高斯朴素贝叶斯模型
from sklearn.naive_bayes import GaussianNB
#创建一个model1用于存储高斯朴素贝叶斯模型
model1 = GaussianNB()
#模型训练
model1.fit(x,y)
model1.score(x,y)
#使用高斯朴素贝叶斯模型进行预测
y1_predict_2019 = model1.predict(x_predict_2019)
print('高斯朴素贝叶斯模型预测的结果:',y1_predict_2019)
if y1_predict_2019 == 0:
    print('次年房价不会大幅度上涨')
elif y1_predict_2019 == 1:
    print('次年房价会大幅度上涨')
else:
    print('无效的结果')

输出结果显示

伯努利朴素贝叶斯和高斯朴素贝叶斯预测出来的结果一样。

朴素贝叶斯包含诺干种变体,常用的变体包括伯努利朴素贝叶斯、高斯朴素贝叶斯、多项式朴素贝叶斯等,其中伯努利朴素贝叶斯适用于样本特征符合伯努利分布的的数据集,高斯朴素贝叶斯适用于样本特征为连续特征且大致符合高斯分布的数据集,而多项式朴素贝叶斯适用于样本特征符合多项式分布的数据集。

 下面通过实例来不同朴素贝叶斯变体的差异

第一个先是伯努利朴素贝叶斯

首先我们使用make_blobs函数生成数据集,并将数据集可视化,然后使用模型进行训练,输出准确率

#导入数据集生成工具
from sklearn.datasets import make_blobs
#导入数据集拆分工具
from sklearn.model_selection import train_test_split
#导入伯努利朴素贝叶斯
#导入画图工具
import matplotlib.pyplot as plt
from sklearn.naive_bayes import BernoulliNB
#生成样本数量为600,分类数为6,随机值为22
x,y = make_blobs(n_samples=600,centers=6,random_state=22)
plt.scatter(x[:,0],x[:,1],c=y,cmap='autumn',edgecolors='k')
plt.show()
#将数据集拆分成训练集和验证集,固定随机值为8
x_train,x_test,y_train,y_test = train_test_split(x,y,random_state=8)
model = BernoulliNB()
model.fit(x_train,y_train)
print('模型得分:{:.3f}'.format(model.score(x_test,y_test)))

输出结果显示

 接下来我们使用图形来探索问题所在

import numpy as np
#导入画图工具
import matplotlib.pyplot as plt
x_min,x_max=x[:,0].min()-0.5,x[:,0].max()+0.5
y_min,y_max=x[:,1].min()-0.5,x[:,1].max ()+0.5
xx,yy = np.meshgrid(np.arange(x_min,x_max,.2),np.arange(y_min,y_max,.2))
z = model.predict(np.c_[(xx.ravel(),yy.ravel())]).reshape(xx.shape)
plt.pcolormesh(xx,yy,z,cmap= plt.cm.Pastel1)
plt.scatter(x[:,0],x[:,1],c=y, cmap=plt.cm. Pastel2,edgecolor='k')
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(), yy.max())
plt.title('BernoulliNB')
plt.show()

输出结果显示

观察此图,伯努利朴素贝叶斯分类器对于连续数值的样本分类结果不太理想,样本数据几乎没有被正确的分类.

下面我们使用高斯朴素贝叶斯进行分类

继续使用上面的数据集,并且使用高斯朴素贝叶斯模型进行训练

#导入高斯朴素贝叶斯模型
from sklearn.naive_bayes import GaussianNB
#导入画图工具
#生成样本数量为600,分类数为6,随机值为22
x,y = make_blobs(n_samples=600,centers=6,random_state=22)
plt.scatter(x[:,0],x[:,1],c=y,cmap='autumn',edgecolors='k')
plt.show()
#将数据集拆分成训练集和验证集,固定随机值为8
x_train,x_test,y_train,y_test = train_test_split(x,y,random_state=8)
model1 =GaussianNB()
model1.fit(x_train,y_train)
print('模型得分:{:.3f}'.format(model1.score(x_test,y_test)))

这里我们就不再查看数据集,直接进行数据集可视化查看分类结果

import numpy as np
#导入画图工具
import matplotlib.pyplot as plt
x_min,x_max=x[:,0].min()-0.5,x[:,0].max()+0.5
y_min,y_max=x[:,1].min()-0.5,x[:,1].max ()+0.5
xx,yy = np.meshgrid(np.arange(x_min,x_max,.2),np.arange(y_min,y_max,.2))
z = model1.predict(np.c_[(xx.ravel(),yy.ravel())]).reshape(xx.shape)
plt.pcolormesh(xx,yy,z,cmap= plt.cm.Pastel1)
plt.scatter(x[:,0],x[:,1],c=y, cmap=plt.cm. Pastel2,edgecolor='k')
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(), yy.max())
plt.title('GaussianNB')
plt.show()

 输出结果显示

观看此图可以发现高斯朴素贝叶斯的分类结果非常理想,样本几乎都放进了正确的分类,由此可知,对于特征为连续数值类型的样本数据来说,高斯朴素贝叶斯更为适用,样本数量越大,其优势会更加明显。

七、K最近邻算法

 K最近邻算法是最简单的机器学习算法之一,也是理论上比较成熟的,运用基于样本估计的最大后验概率规则的判别方法。其思路是在一个特征空间中,如果一个样本附近的k个最近样本的大多数属于某一类别,则该样本也属于这个类别。即给定一个训练集,对于新输入实例,在训练集中找到与该实例最邻近的k个实例,这个k实例中的多数属于某个类,就把该输入实例分类到这个类中。

K最近邻算法的原理可以用一句古话表示:“近朱者赤近墨者黑”

 下面我们进行讲解K最近邻算法在二元分类任务中的应用

首先我们使用make_blobs生成数据集

#导入相关库
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
#生成数据集
data = make_blobs(n_samples=100,centers=2,random_state=10)
x,y = data
plt.scatter(x[y==1,0],x[y==1,1],cmap=plt.cm.summer,edgecolors='k',marker='^')
plt.scatter(x[y==0,0],x[y==0,1],cmap=plt.cm.summer,edgecolors='k',marker='o')
plt.show()

 输出结果显示

从图中我们可以得知数据集一共就两类。

import numpy as np
model = KNeighborsClassifier()
model.fit(x,y)
#数据可视化
x_min,x_max = x[:,0].min() -1,x[:,0].max() +1
y_min,y_max = x[:,1].min() -1,x[:,1].max() +1
xx,yy = np.meshgrid(np.arange(x_min,x_max,.02),np.arange(y_min,y_max,.02))
z = model.predict(np.c_[xx.ravel(),yy.ravel()])
z = z.reshape(xx.shape)
plt.pcolormesh(xx,yy,z,cmap=plt.cm.Set3)
plt.scatter(x[y==1,0],x[y==1,1],cmap=plt.cm.summer,edgecolors='k',marker='^')
plt.scatter(x[y==0,0],x[y==0,1],cmap=plt.cm.summer,edgecolors='k',marker='o')
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(),yy.max())
plt.title('classsfication knn')
plt.scatter(5.49,-3.67,marker='*',c='red',s=100)
plt.show()

输出结果显示

K最近邻算法基于数据集创建了一个分类模型,并且将数据分为两类,五角星代表新的数据点所在的位置。我们尝试输出这个分类

print('新的数据点[-5.49,-3.67]的分类是:', model.predict([[-5.49, -3.67]]))

输出结果显示

K最近邻算法不仅可以用于分类,还可以用于回归,接下来进行K最近邻算法的回归分析

生成数据集

from matplotlib import pyplot as plt
from sklearn.datasets import make_regression
#定义x和y,此时只有一个特征
x,y=make_regression(n_samples=50 , n_features=1,noise = 10 , random_state=3)
plt.scatter(x,y,edgecolors='r',c='y')
plt.show

输出结果显示

这里我们设置样本特征为1,并且添加了标准差为30的噪声,横轴代表样本特征的数值,纵轴代表样本的预测值。

下面使用K最近邻算法进行回归分析

from sklearn.neighbors import KNeighborsRegressor
import numpy as np
#定义K最近邻回归模型
KNR = KNeighborsRegressor()
#训练
KNR.fit(x,y)
#定义横纵坐标
z = np.linspace(-3,2,50).reshape(-1,1)#这里的50代表元素数
#画图
plt.scatter(x,y,edgecolors='r')
plt.plot(z,KNR.predict(z),c='r',linewidth=2)
plt.show()

输出结果显示

从图中可以发现,模型拟合程度并不是很好,大量数据点都没有被模型覆盖到。

接下来,我们对模型进行优化

K最近邻算法有一个近邻数参数,我们尝试对参数进行调整,默认参数为5,我们可以设置为2

from sklearn.neighbors import KNeighborsRegressor
import numpy as np
#定义K最近邻回归模型
KNR = KNeighborsRegressor(n_neighbors=2)
#训练
KNR.fit(x,y)
#定义横纵坐标
z = np.linspace(-3,2,50).reshape(-1,1)#这里的50代表元素数
#画图
plt.scatter(x,y,edgecolors='r')
plt.plot(z,KNR.predict(z),c='r',linewidth=2)
plt.show()

输出结果显示

显而易见,此时的结果拟合比较好,模型覆盖了大多数数据点,下面我们输出评分结果

score = 0
value_best = 0
for k in range(2,10):
    KNR2 = KNeighborsRegressor(n_neighbors=k)
    KNR2.fit(x,y)
    max_score = KNR2.score(x,y)
    if max_score > score:
        score = max_score
        value_best = k
print("最佳k值为:",value_best)
print("此时模型的评分为:",score)

输出结果显示

此时模型评分高达98%,由此可知,调整模型参数能够有效改善模型的准确率。

下面我们使用K最近邻算法进行一个实战演练

首先从机器学习库中下载一个关于申请国外大学相关指标的数据集

我们使用pandas库中的read_csv函数读取csv文件

#导入相关库
import pandas as pd
from sklearn.neighbors import KNeighborsRegressor
#查看数据集
Admission = pd.read_csv('../国外大学相关指标数据集/Admission_Predict.csv')
Admission.head()

输出结果显示

pandas成功载入数据集,并且默认显示了前五行

关于该数据集的解释

第九个特征是我们任务中要预测的目标

下面进行数据集处理

#处理数据集
Admission = Admission.drop(['Serial No.'],axis=1)
Admission.head()

输出结果显示

从图中我们可以发现删掉了Serial No.这一列,因为这仅仅代表数据的序号,并没有实质性的作用

下面我们对数据集进行拆分,并且评估

#导入拆分工具进行数据拆分
from sklearn.model_selection import train_test_split
import numpy as np
#定义x,y
x = Admission.drop(['Chance of Admit'],axis=1)
y = Admission['Chance of Admit'].values
#划分训练集测试集
x_train,x_test,y_train,y_test = train_test_split(x,y,random_state=42)
#创建模型进行训练
KNR = KNeighborsRegressor()
KNR.fit(x_train,y_train)
#模型评估
print("测试集评估:",KNR.score(x_train,y_train))
print("训练集评估:",KNR.score(x_test,y_test))

输出结果显示

模型预测

#模型预测
#创建一个测试数据点
test_data = np.array([[337,118,4,4.5,4.5,9.65,1]])
#预测
pre = KNR.predict(test_data)
print("小p同学出国留学的概率",pre)

输出结果显示

修改模型参数,对模型进行调优,重新预测

#模型调优
#修改n_neighbors
KNR2 = KNeighborsRegressor(n_neighbors=3)
KNR2.fit(x_train,y_train)
#模型评估
print("修改n_neighbors测试集评估:",KNR2.score(x_train,y_train))
print("修改n_neighbors训练集评估:",KNR2.score(x_test,y_test))
#修改权重
KNR3 = KNeighborsRegressor(weights="distance")
KNR3.fit(x_train,y_train)
#模型评估
print("修改权重测试集评估:",KNR3.score(x_train,y_train))
print("修改权重训练集评估:",KNR3.score(x_test,y_test))

输出结果显示

对数据进行归一化处理

#对数据进行归一化处理
from sklearn.preprocessing import MinMaxScaler
#数据预处理
np.set_printoptions(precision=3)
x_new = MinMaxScaler().fit_transform(x)
print(x_new)

预测新数据

#预测新数据
pre_new2 = KNR2.predict(x_new)
pre_new3 = KNR3.predict(x_new)
print("修改n_neighbors后,小p同学出国留学的概率",pre_new2[0])
print("修改权重后,小p同学出国留学的概率",pre_new3[0])

输出结果显示

由此发现,预测概率下降到正常范围。

八、神经网路

 神经网络是一种算法结构,它能让机器进行自我学习,常见的例子有语音命令、音乐创作和图像识别等。

在前文中我们讲到线性逻辑回归模型,线性回归可以视为最简单的单层神经网络(单层感知机),多层感知机实际就是单层网络的扩展,其算法在过程里添加了隐藏层,然后在隐藏层重复进行上述加权求和计算,然后再把隐藏层所计算的结果用来生成最终结果。

多层感知机算法模型,一般由输入层、隐藏层、输出层、输出层3个部分组成。

图中,由左至右,分别是输入层、隐藏层、输出层。每层中都有诺干个神经元,也叫节点。输出层如果是多节点,则模型常常用于解决分类问题。其中每一个箭头指向的连线上,都要有一个权重值。

激活函数是神经网络的重要组成部分之一,神经网络在不使用激活函数的情况下,它的每一层的输入都是上一层的线性输出。无论该神经网络有多少层,输出与输入都是线性相关的,这样有没有隐藏层就没有太大区别,也就变成了最原始的感知机,没有太多意义。因此需要引入非线性函数即激活函数,这样多层神经网络的输出不再是输入的线性组合,可以逼近任意函数,多层神经网络的真正效果才能显现出来。

下面介绍常用的激活函数:

Identity函数,节点的输入等于输出,对于样本特征不做处理,返回值是f(x)=x。适用于潜在行为是线性任务。

Sigmoid函数,返回的结果是非线性的f(x)=1/(1+exp(-x)),对于任意输入,其输出范围都是0~1。

tanh函数,对于任意输入,该函数都会将输入转化为一个-1~1的值。

relu函数,是一个分段函数,对于某一输入,当它小于0时,输出为0,否则f(x)=x。

cos函数,余弦函数。

sinc函数,主要用于信号处理。

以上函数均有优缺点,如Sigmoid函数、tanh函数在实际案例中均有不错的效果,但是它们又有梯度消失以及开销巨大的指数运算的问题等。

下面我们使用鸢尾花数据集,对神经网络进行参数调节

首先介绍各个参数的含义:

activation:是在8.3.1小节中提到的隐藏单元进行非线性化的方法,这里一共有4种:identity,logistic,tanh,relu。

alpha值:和线性模型的alpha值是一样的,是一个L2惩罚项,用来控制正则化的程度,默认的数值是0.0001

hidden_layer_sizes参数:该参数是比较重要的隐藏层的数量参数。默认情况下,hidden_layer_sizes的值是[100,]表示模型中只有两个隐藏层,每层有十个节点。

solver参数:该参数决定了对逻辑回归损失函数的优化方法,有4种算法可以选择,分别是"liblinear","lbfgs","newton-cg","sag"。

liblinear:使用开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数。

lbfgs:牛顿法的一种,利用损失函数二阶导数矩阵即黑森矩阵来迭代优化损失函数。

sag:随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别就是每次迭代仅用一部分样本来计算梯度,适合于样本数据多的时候。

下面我们对探索参数,我们采用控制变量法进行试验,首先,我们选择solver=lbfgs

导入MLP神经网络

#导入相关库
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPClassifier

#定义一个model用于接收神经网络

datasets = load_iris()
#定义x,y
x = datasets.data[:,:2]
y = datasets.target
#划分数据集,划分比为8:2,随机值为42
x_train,x_test,y_train,y_test = train_test_split(x,y,random_state=42,train_size=0.8)

model = MLPClassifier(solver='lbfgs')
#训练模型
model.fit(x_train,y_train)
print(model.score(x_train, y_train))
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import ListedColormap
camp_light = ListedColormap(['#FFAFAA','#AAFFDA','#FAAAFF'])
camp_bold = ListedColormap(['#FF00AA','#00FF0F','0FA0FF'])
x_min,x_max, = x_train[:,0].min() -1,x_train[:,0].max() +1
y_min,y_max = x_train[:,1].min() -1,x_train[:,1].max() +1
xx,yy = np.meshgrid(np.arange(x_min,x_max,.02),np.arange(y_min,y_max,.02))
z = model.predict(np.c_[xx.ravel(),yy.ravel()])
z = z.reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx,yy,z,cmap=camp_light)
#将数据特征用散点图表示出来
plt.scatter(x[:,0],x[:,1],c=y,edgecolors='k',s=60)
plt.xlim(xx.min(),xx.max())
plt.ylim(yy.min(),yy.max())
#设定图题
plt.title("MLPClassifier:solver=lbfgs")
plt.show()

print('MLPClassifier:solver=lbfgs得分:{:.2f}%'.format(model.score(x_train,y_train)*100))

输出结果显示

接下来,我们 将隐藏层的节点减少到20个

我们添加这一个参数即可

model = MLPClassifier(solver='lbfgs',hidden_layer_sizes=[20])

输出结果显示

显然,模型的有了提升

我们继续调参,将隐藏层数量增加到2层

model = MLPClassifier(solver='lbfgs',hidden_layer_sizes=[20,20])

输出结果显示

可以看到,模型分数反而降低。

下面我们调整激活函数,看一下效果

model = MLPClassifier(solver='lbfgs',hidden_layer_sizes=[20,20],activation='tanh')

输出结果显示

由此看到,分类器决定的边界线变成了平滑的曲线,并且模型分数也有提高。

下面我们调节模型复杂度

model = MLPClassifier(solver='lbfgs',hidden_layer_sizes=[20,20],activation='tanh',alpha=1)

 输出结果显示

 发现此时模型分数又有提高。

到此,我们调节四种参数来分析模型,发现调节隐藏层减少到20与模型复杂度调节到1模型的分数一致,由此可以得出结论:模型越复杂,分类准确率越高。

ps:本人也是大学生,本篇文章也是根据我所学的基础知识和案例写出来的,如果有什么不足的地方提出来,我会修改,谢谢大家的支持,文章会持续更新。。。。。。


  • 41
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值