人工智能开发实战机器学习算法解析
内容提要
- 线性回归
- 逻辑回归
- KNN
- 其它机器学习算法
一、线性回归
1、什么是线性回归
线性回归是一种基于数理统计的回归分析方法,在此方法中通过测定多个变量之间的相互依存关系来建立变量间的数学模型,并进一步用于测定这些变量之间的相关程度
在基本概念层面上而言,线性回归就是旨在完成一个特定类型的数学模型。此模型的核心功能是接收一组数值型输入变量,并通过数学关系计算出相应的结果并返回。这些计算出的结果用于预测目标变量的变化趋势,并且这些变化趋势通常是平滑且无间断的。
线性回归位于N维空间中寻找一条直线、一个平面或一个超平面以配合提供的数据进而预测新增的数据在线性回归模型中公式表示为y = Wx + b其中W代表权重矩阵而b代表偏置向量
2、线性回归案例
生成一些数据x和y分别表示时间投入和考试成绩,在寻找一条最佳拟合直线以使这条直线最佳地契合这些数据点时,在复习过程中时间和分数之间的关系通过图像表示(如图1所示)。
在这个回归任务中,在寻找最优拟合直线的过程中,默认的目标是以最小化误差为基准。通过回归分析获得的直线如图2所示。

希望拟合后的线上每一个样本点的预测值与实际值之间的差异最小。即通过最小化所有样本点预测值与实际值之差的总和来确定最优拟合线。真实值与预测值之间的差异在二维空间中表现为两者之间的距离。从而将寻找最优拟合线的问题转化为寻找使得所有点到该直线的距离之和最小的直线。
计算距离常用的方法有L1距离和L2距离等。

L1距离公式为

,(x1,y1)是起点的坐标,(x2,y2)是终点的坐标。
L2距离公式为

,(x1,y1)是起点的坐标,(x2,y2)是终点的坐标。
提示: 当探索复习时间与考试成绩的最佳拟合曲线时,在此过程中也可以应用L1或L2距离来进行建模。在这里采用的是L2距离来完成拟合过程。
我们的目标因此得以明确:所有样本点x(p)与其拟合线上相应预测值与真实值y之间的距离总和需要最小化。换句话说

要尽可能小,结合

,使得

尽可能小,由于x和y是已知的,所以需要找到k和b。
在机器学习中,斜率k一般称为权重W,截距b称为偏置b,y(p)是真值,

是预测值。这个过程就是使用最小二乘法解决问题的思路。
在机器学习领域中,在分析具体的问题时需要确定相应的损失函数;为了确定这些损失函数,则需要对其进行最优化处理;这样就能构建出适用于该任务的机器学习模型;针对本问题而言

该损失函数在基于已知变量x与y的情况下,则要求确定参数k与b使其达到最小值。
3、数学方法解决线性回归问题
案例见上,步骤如下:
先导入必要的库。
希望拟合后的线上每一个y与其对应的样本点x(p)之间的差异最小化;即通过使所有样本点x(p)的真实值与预测值之间的差异总和达到最小来确定最优拟合线;这种差异在二维空间中表现为两点之间的距离;因此将寻找最优拟合线的问题转化为寻找两点间最短路径的问题
计算距离常用的方法有L1距离和L2距离等。
二、逻辑回归
1、什么是逻辑回归
在在线性回归模型中(y = f(x)),当输出结果y不是一个确定的数值而是一个概率p时,则相应的公式被重新定义为p = f(x)。这种情况下,在线性回归的基础上推导出计算概率的过程需要引入一个中间步骤(intermediate function),即从将线性回归模型用于生成具体预测值过渡到计算概率的过程中需要引入一个中间步骤

当未引入中间计算环节时,则归因于一个回归问题的本质;而一旦引入了中间计算环节后,则转为一个分类问题。
线性回归中有公式

对于逻辑回归模型而言,在这种情况下变量x可以取任何实数值(或表示为一个多维向量),其输出结果被限制在0到1之间。为了适应分类任务的需求,在线性回归模型的基础上将其预测函数转换为y = \sigma(w^Tx + b)的形式。

引入为新的特征变量能够计算出概率值。常用方法来处理这种情况,并采用sigmoid()函数作为激活机制。其形式如下:

,sigmoid()函数图像如图所示。

通过在坐标轴上进行描绘后生成 sigmoid() 函数图像的形式图谱,则可观察其变化趋势。

2、逻辑回归案例
该行根据客户的信用评分来判断是否提供其信用卡此处假定横轴x表示客户的信用评分等级分数域范围从0到90分纵轴y则代表其工作稳定性在这些设定下绘制若干数据点用三角形标记表示该客户不符合条件无法获得卡片而用五角星标记表示符合条件能够申领到卡片如图所示

3、数学方法解决逻辑回归问题
在在线性回归模型中,结果呈现线性关系。为了使因变量y与自变量之间的预测值之间的距离最小化而得到最佳拟合效果,在这种情况下可以通过计算最小化这一距离来确定模型参数。
然而,在逻辑回归模型中,算法生成的输出值代表概率值。由于这些概率值并不直接对应于样本之间的距离度量,在这种情况下无法直接计算它们之间的距离。因此通常会采取某种处理方法来解决这个问题,并采用特定的损失函数来评估模型的性能表现。其中x变量表示为逻辑回归算法得出的结果变量
对于该公式

,损失函数的图像如图所示。

说明:
由两个子函数组成,在编程实现时会遇到挑战。因此建议将它们整合成一个综合的损失函数。

当y=1时,

当y=0时,

这里有一个样本,当有n个样本时,损失函数为

其中

按照解决线性回归问题的思路,应该算出它的数学公式解,
然而这个表达式无法通过显式数学公式求解,在此采用梯度下降法作为解决方案来应对该逻辑回归问题。
4、利用TensorFlow解决逻辑回归问题
在机器学习中应用梯度下降法来实现逻辑回归模型的训练,在machine_learning项目中创建一个新的Python文件Logistic_regression.py,并绘制一条区分线来判断是否向用户发放信用卡两类数据。
(1)导入必要的库
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
(2)训练逻辑回归
# 创造数据
raw_data_X = [[1.85, 1.05],[1.57, 2.63], [2.28, 1.42],
[2.28, 3.64], [1.94, 3.68],[2.09, 2.66], [1.49, 3.66],
[0.12, 1.12], [0.25, 1.04],[0.23, 0.54], [0.83, 1.49],
[0.95, 0.09], [0.46, 1.63], [0.26, 1.03], ]
raw_data_Y = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1];
data = np.array(raw_data_X)
label = np.array(raw_data_Y)
data = np.hstack(data).reshape(-1,2)
label = np.hstack(label).reshape(-1,1)
label1 = label.reshape(1,-1)[0]
plt.scatter(data[label1 == 0, 0], data[label1 == 0, 1], marker="*")
plt.scatter(data[label1 == 1, 0], data[label1 == 1, 1], marker="^")
plt.show()
x = tf.placeholder(tf.float32,shape=(None,2))
y_ = tf.placeholder(tf.float32,shape=(None,1))
# tf.random_normal()函数用于从服从指定正态分布的数值中取出指定个数的值
# tf.random_normal(shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=None)
weight = tf.Variable(tf.random_normal([2,1]), dtype=tf.float32)
bias = tf.Variable(tf.constant(0.1, shape=[1]))
# tf.nn.sigmoid()是激活函数
y_hat = tf.nn.sigmoid(tf.matmul(x, weight) + bias)
# 不适用该损失函数
# cost = tf.reduce_sum(tf.square(y_ - y_hat))
# 损失函数
cost = - tf.reduce_mean(y_ * tf.log(tf.clip_by_value(y_hat, 1e-10, 1.0)) + (1 - y_) * tf.log(tf.clip_by_value((1 - y_hat), 1e-10, 1.0)))
# 梯度下降
optimizer = tf.train.AdamOptimizer(0.001)
train = optimizer.minimize(cost)
#开始训练
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
plt.ion()
for i in range(8000):
sess.run(train,feed_dict={x:data,y_:label})
#画出训练后的分割函数
#mgrid()函数产生两个300×400的数组:0~3每隔0.1取一个数,共300×400个
xx, yy = np.mgrid[0:3:.1,0:4:.1]
if (i % 20) == 0:
# np.c_用于合并两个数组
# ravel()函数将多维数组降为一维,仍返回array数组,元素以列排列
grid = np.c_[xx.ravel(), yy.ravel()]
probs = sess.run(y_hat, feed_dict={x:grid})
# print(probs)
效果如图:

三、KNN
1、什么是KNN
一种惰性学习算法KNN(k-近邻法)是基于实例的学习方法,在不需要显式地提取问题域中的特征空间的情况下直接存储训练数据集;它通过计算测试样例与训练集中各个样本之间的距离来进行分类或回归预测;在监督学习方法中作为一种重要的非参数化分类器被广泛使用
KNN是一种用于分类的方法。通过某种距离度量确定在训练集中与给定待测样本最邻近的k个样本点,在这些近邻样本的基础上进行分类判断:待测样本所属类别与哪些类别间距离较近,则归入相应类别中
2、KNN案例
在一个二维平面中存在三种不同的图形具体包括五角星三角形与正方形这些图形的特点与其位置(即对应于其x轴和y轴坐标)具有重要关联目前引入一个新的数据点需要将其归入这三类之一通过K近邻算法(KNN)来实现分类过程
二维平面示意图如图:

那么如何使用KNN将新的点进行分类呢?需要给KNN制订步骤:
(1)计算距离
(2)取出距离最近的点,找到新的点与哪一类更接近,观察分类结果
KNN最简单的思想是:
识别出与预测数据最接近的k个样本后,在投票环节中将这些样本对应的标签进行统计。最终被选中的票数最多的标签即被确定为预测数据的分类结果。
当k=1时,K近邻算法就变成了近邻算法。
研究不同k值对分类表现的影响情况,并通过L2距离构建三种分类模型,并绘制其对应的决策边界线。每个决策边界的同一侧区域归于同一类别,在二维坐标系中展示这些区域,并使用不同颜色区分表示各个类别。
k=1时的决策边界,k=5时的决策边界如图所示。

3、数学方法解决KNN问题
(1)导入必要的库
import matplotlib.pyplot as plt
from collections import Counter
from math import sqrt
import numpy as np
NumPy库用于处理数据类型转换;Matplotlib库中的pyplot模块用于生成图像;Math模块提供了平方根计算功能;而Collections中的Counter类则用于统计标签数量。
(2)在二维平面上创造一些数据
raw_data_X = [[3.85, 3.05],
[1.57, 2.63],
[4.28, 4.42],
[5.68, 3.64],
[1.94, 3.68],
[2.49, 2.66],
[0.49, 3.66],
[0.12, 1.12],
[2.25, 2.04],
[0.23, 0.54],
[1.33, 1.49],
[2.35, 0.09],
[1.46, 1.63],
[3.66, 3.93],
[5.11, 0.39],
[5.69, 1.14],
[4.03, 2.49],
[4.92, 1.62],
[5.26, 2.05],
[4.26, 2.05],
[5.84, 1.31]
]
raw_data_Y = [0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2]
说明:
将数据划分为三类;其取值范围设定为0至8之间;其取值范围设定为0至5之间。允许用户自定义或通过生成随机数来创建数据;建立两个列表变量;第一个列表命名为raw_data_X用于存储坐标数值;第二个列表命名为raw_data_Y用于存储对应的标签信息。
(3)将列表转换为NumPy
x_train = np.array(raw_data_X)
y_train = np.array(raw_data_Y)
(4)新建一个测试点
x_test = np.array([3.35, 2.46])
(5)绘制散点图
plt.xlabel('x轴')
plt.ylabel('y轴')
plt.scatter(x_train[y_train == 0,0], x_train[y_train == 0,1], marker = "*")
plt.scatter(x_train[y_train == 1,0], x_train[y_train == 1,1], marker = "^")
plt.scatter(x_train[y_train == 2,0], x_train[y_train == 2,1], marker = "s")
plt.scatter(x_test [0], x_test [1], marker = "o")
plt.show()

(6)创建训练函数
def train(X, y):
Xtr = X
Ytr = y
return Xtr, Ytr
(7)创建预测函数
def predict_math (X, xtrain, ytrain):
# 求L2距离
distances = [sqrt(np.sum((X_train - X) ** 2)) for X_train in xtrain]
# 对数组进行排序,返回的是值的索引值
nearest = np.argsort(distances)
# 取出前3个离得最近的点的标签
k = 3
topK_y = [ytrain[i] for i in nearest[:k]]
# 计数,取到键值对。键:标签;值:个数
votes = Counter(topK_y)
# 在键值对中值最多的键
print(votes.most_common(1)[0][0])
(8)调用训练函数与预测函数,完成预测
xtrain, ytrain = train(x_train, y_train)
predict_math (x_test, xtrain, ytrain)
(9)修改预测函数
def predict_math(X, xtrain, ytrain):
# 求L2距离
distances = [sqrt(np.sum((X_train - X) ** 2)) for X_train in xtrain]
# 对数组进行排序,返回的是值的索引值
nearest = np.argsort(distances)
# 取出前3个离得最近的点的标签
k = 3
topK_y = [ytrain[i] for i in nearest[:k]]
# 计数,取到键值对。键:标签;值:个数
votes = Counter(topK_y)
# 在键值对中值最多的键
print(votes.most_common(1)[0][0])
# 得到最接近的3个点的索引值
k = 3
topK_X = nearest[:k]
for i in range(3):
# 绘制预测点与最接近的3个点连成的直线
plt.plot([X[0], xtrain[topK_X[i]][0]], [X[1], xtrain[topK_X[i]][1]])
# 绘制预测点与最接近的3个点之间的长度
plt.annotate("%s"%round(distances[topK_X[i]], 2), xy=((X[0] + xtrain[topK_X[i]][0]) / 2,(X[1] + xtrain[topK_X[i]][1]) / 2))
plt.xlabel('x轴')
plt.ylabel('y轴')
plt.scatter(x_train[y_train == 0, 0], x_train[y_train == 0, 1], marker="*")
plt.scatter(x_train[y_train == 1, 0], x_train[y_train == 1, 1], marker="^")
plt.scatter(x_train[y_train == 2, 0], x_train[y_train == 2, 1], marker="s")
plt.scatter(x_test[0], x_test[1], marker="o")
plt.show()
k=3时将具有五个尖端的图形归类于第0个类别,并将其视为其所属类别。此时直接输出显得不够直观,请参考图示以获得更清晰的理解

4、利用TensorFllow解决KNN问题
# 导库
import tensorflow as tf
# 完成预测
def predict_tf(X, xtrain, ytrain):
# 定义变量大小
xtr = tf.placeholder("float", [None, 2])
xte = tf.placeholder("float", [2])
# 计算L2距离
# tf.negative()函数用于取相反数
# 调用reduce_sum(arg1, arg2)时,参数arg1即为和的数据,arg2可以取0和1
# 当arg2 = 0时,是纵向对矩阵求和,原来的矩阵有几列就得到几个值
# 当arg2 = 1时,是横向对矩阵求和;当省略arg2参数时,默认对矩阵所有元素进行求和
distance = tf.sqrt(tf.reduce_sum(tf.square(tf.add(xtr, tf.negative(xte))), reduction_indices=1))
with tf.Session() as sess:
# 添加用于初始化变量的节点
sess.run(tf.global_variables_initializer())
# 近邻算法:将测试集与训练集进行对比,返回误差最小的下标
nn_index = sess.run(distance, feed_dict={xtr: xtrain, xte: X})
# 对数组进行排序,返回的是值的下角标
nearest = np.argsort(nn_index)
# 取出前3个离得最近的点的标签
k = 3
topK_y = [ytrain[i] for i in nearest[:k]]
# 计数,取到键值对。键:标签;值:个数
votes = Counter(topK_y)
# 在键值对中值最多的键
print(votes.most_common(1)[0][0])
说明:
其核心优势在于其基本原理较为直观,在实际应用中通常无需进行复杂的训练步骤
仅仅将训练集数据存储起来即可完成其整个计算流程的算法设计是相当简单的。因此算法无需投入大量时间用于其训练阶段。然而尽管算法无需投入大量时间用于其计算过程本身——即仅进行数据存储——但所有的时间却主要用于测试环节。
在训练集中共有m条记录和n项指标。当进行预测时需要逐一计算其与训练集中全部m条记录的距离。每次计算两个数据之间的距离所需的时间复杂度为O(n)。统计所有m条记录两两之间的距离所需的总时间复杂度为O(m×n)。
这与常规情况不符,在常规情况下认为训练时间应较长而测试时间相对较短
四、其它机器学习算法
1、支持向量机
支持向量机(SVM)作为一种监督式学习算法,在数据科学领域具有重要地位。它不仅能够有效地进行数据分类与预测分析( regression analysis),还特别适用于解决复杂的模式识别问题( pattern recognition)。在实际应用中,支持向量机模型通常被用来解决分类问题( classification problem)。
该算法基于特征值构建了一个n维的空间,并将数据点投影至该空间中;随后通过寻找一个超平面来实现对这一空间中数据的分类功能;如图所示为具体实施效果示意图

2、决策树
决策树是一种有监督学习的算法,主要用于分类问题中。
决策树本质上可以被视为这样一种结构:它上面有多个分支节点,每一个分支都代表着一个可能的选择;而叶子节点则预示着最终的决定。

3、随机森林
随机森林是有监督的集成学习模型,主要用于分类和回归。
随机森林建立了很多决策树并将其集成,以获得更准确、更稳定的预测。
4、K-Means
K-均值聚类(K-Means)是一种无监督学习算法。
聚类算法通过将不同类别中的数据样本分组为一系列的簇体,从而使得同一簇体内的数据样本与其他簇体相比更具一致性
K-means clustering algorithm aims to partition the data into k mutually exclusive clusters, where each cluster is characterized by a representative point known as the cluster centroid. The centroid represents the central tendency of its associated cluster, serving as a prototype for all data points within that cluster.
更多精彩内容请关注本站!
