机器学习分类算法项目

摘要

本项目围绕机器学习分类算法展开, 以支持向量机(support vector machine,SVM)为主要研究对象,探究其分类性能、模型改进与优化算法。SVM和Logistic回归模型都可以用于解决二分类问题,但模型设计的思路不同,因此希望能够比较两者在分类性能上的差异。项目过程中代码完全基于R语言实现,主要以二维样本数据为研究对象,生成模拟数据并基于经典硬间隔SVM模型和Logistic回归模型分别进行建模与训练,在测试集上对模型进行验证,最终比较两者的分类效果差异。实验结果表明,当样本数据本身区分度不明显时,两种分类模型效果均较差,但Logistic模型明显优于经典硬间隔SVM;当样本数据本身具有明显的差异性时,两种分类模型效果均较好,SVM略优于Logistic。此外,还对改进后的SVM模型(核函数由线性函数更换为高斯核函数)进行性能测试,发现其在区分度不明显的数据集上显著优于经典硬间隔SVM,说明其显著提升了其在非线性可分数据上的分类效果;但在区分度较明显的数据集上分类效果反而略逊于经典SVM模型。最后,对两篇有关SVM改进模型的文献进行了阅读与调研,总结了软间隔SVM模型在正则项和损失项拓展方面的研究进展,并介绍了柔性套索惩罚和快速截断Huber损失等改进方法。

关键词: 机器学习分类算法、二分类、支持向量机(SVM)、Logistic回归、硬间隔、软间隔、高斯核函数、改进的SVM模型、柔性套索惩罚、快速截断Huber损失、R语言

项目概述

问题背景

人工智能的概念是在1956年首次被提出,其目标旨在希望通过计算机模拟人的思维能力或智能行为,从而让计算机能够像人类一样进行思考。目前,人工智能已经在机器翻译、智能控制、图像识别、语音识别、游戏博弈等领域得到广泛的应用。

机器学习作为人工智能的一个发展方向,起源于20世纪50年代的感知机数学模型,其目标是使得机器能够像人类一样具有学习能力。机器学习的基本过程主要是基于样本数据(客体)去训练/学习某个模型或决策函数(主体)。一般而言,正则化框架下的机器学习过程主要由学习机、损失项和正则项(惩罚项)三个部分构成,最终通过学习得到模型。

支持向量机(support vector machine,SVM)最早由Cortes和Vapnik二人于1995年为解决二分类问题而提出[^1]。作为经典的机器学习模型之一,SVM有坚实的统计理论基础,算法实现容易,且决策函数具有很强的几何含义。由于其在模式识别等数据分析问题中的优越表现,SVM如今已成为最经典的判别分析方法之一。与SVM相类似,广义线性回归统计模型中的Logistic回归模型同样也可用于解决二分类问题。本质上来说,两种方法都注重研究一组协变量X_1, …, X_p是如何影响二元的响应变量Y的,在用途上具有极大的相似性,因而希望研究并比较两者分类效果的差异性。

除此之外,SVM作为一种经典且基础的机器学习算法,在漫长的发展历程中也经历了多次迭代,有多种多样的改进版本。最基本的版本为硬间隔SVM,但由于实际的样本数据很可能不满足线性可分的理想情况,又发展出了采用不同求解算法的软间隔SVM模型以及基于核函数升维思想实现的非线性SVM,基于软间隔SVM模型又集中在模型损失项与正则项两个方面进行了理论上的拓展。这样的发展是永无止境的,在此希望对过去的部分研究改进成果进行理论总结与代码实现,以更好地了解SVM模型的发展现状。

项目任务

在本次项目中,需要随机生成模拟数据,并在该样本数据基础上分别利用经典SVM模型与Logistic模型进行统计建模,同时对比两者的分类效果;此外还需要总结并实现部分改进版本的SVM算法,分析其预测效果。具体而言可细分为如下任务:

  • 任务1:随机生成200条模拟数据并将其分为训练数据集与测试数据集,利用训练数据集分别基于经典硬间隔SVM模型与Logistic广义线性回归模型建立统计模型,实现样本数据的分类且在测试数据集上进行验证,比较两者的分类效果差异。

  • 任务2:代码实现某一种改进版本的SVM模型,简单测试其性能并将其分类结果与经典版本进行对比。

  • 任务3:查阅SVM模型改进相关的文献,基于正则化框架对于文献中涉及的模型(学习机、损失项、正则项)、创新点与求解算法进行重述与总结。

项目过程

本项目代码部分完全基于R语言实现,主要涉及样本模拟数据的生成,以及SVM(经典与改进版本)与Logistic回归模型的建立、训练与测试。

模拟数据生成

本项目中涉及到的样本数据完全由模拟方法生成。具体而言,不论是SVM还是Logistic回归模型,其目的都是为了研究一系列协变量对于一个二元的响应变量的影响。为方便起见,选择采用协变量的维度为二维,即二元响应变量Y只由两个变量X_1, X_2决定。在生成数据时,为了较好地区分出两类数据,分别在正态总体下以均值为0和均值为1生成两组模拟数据(同一条数据中的两个变量X_1, X_2来自同一均值的总体),并分别打上分类标签(即对应Y的取值为)0或1:

1
2
3
4
5
6
7
8
9
10
11
12
set.seed(123) #设置随机种子,固定每次运行程序生成的随机数,使结果可重复
n <- 200 # 每个类别的数据点数

# 生成类别0的数据
x1 <- matrix(rnorm(n * 2, mean = 0), ncol = 2)
y1 <- rep(0, n)
# 生成类别1的数据
x2 <- matrix(rnorm(n * 2, mean = 1), ncol = 2)
y2 <- rep(1, n)
# 合并数据
x <- rbind(x1, x2)
y <- c(y1, y2)

绘制样本点对应的散点图,初步观察其分类情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 加载 ggplot2 包
library(ggplot2)

# 创建数据框
data <- data.frame(x1 = x[, 1], x2 = x[, 2], y = factor(y))

# 设置点的大小和透明度
p <- ggplot(data, aes(x = x1, y = x2, color = y)) +
geom_point(size = 3, alpha = 0.7) + # 调整点的大小和透明度
scale_color_manual(values = c("blue", "red")) +
labs(x = "x1", y = "x2", color = "Class") +
theme_minimal()

# 调整背景和边界线
p + theme(panel.background = element_rect(fill = "white", color = "black"),
panel.border = element_rect(color = "black", fill = NA),
axis.line = element_line(color = "black"))

ggsave("2.png", plot = p, width = 6, height = 6, units = "in", dpi = 300)

观察上左图可知,由于基于正态总体生成模拟数据时仅制定了均值而未指定方差(默认为1),导致令均值为0和1的情况下两类数据没有办法明显的区分开来,这样的分类效果显然是不好的。经过调试,当设置两类数据均值分别为0和5时,数据点呈现良好的区分性(如上右图所示)。

为便于后续的模型训练,还需要将样本模拟数据分成训练集与测试集两部分,根据经验,较为合适的数据集数量比例为7:3,即样本数据中的70%为训练集,另外30%为测试集用于验证。

1
2
3
4
5
6
7
8
9
10
# 将数据分为训练集和测试集
train_index <- sample(1:(2 * n), 0.7 * 2 * n)
x_train <- x[train_index, ]
y_train <- y[train_index]
x_test <- x[-train_index, ]
y_test <- y[-train_index]

# 合并
train_data <- cbind(x_train, y_train)
test_data <- cbind(x_test, y_test)

在此对部分训练集数据进行罗列:

1
2
#观察数据集
head(train_data,10)
x.1 x.2 y
1 5.8641525 2.78936689 1
2 -1.9666172 -0.72306597 0
3 0.8215811 -0.57438869 0
4 -1.2512714 0.84573154 0
5 1.3686023 0.09049665 0
6 -0.2153805 2.41677335 0
7 6.0466288 5.10719041 1
8 1.0057385 0.68430943 0
9 4.6738561 3.67224452 1
10 -0.4727914 -1.28471572 0

基于经典硬间隔SVM模型的建模

硬间隔支持向量机是一种基于线性可分数据集的分类模型。线性可分,意味着可用一条直线将两类数据分开。显然这样的直线有无穷多条,但对应直线的上下移动又因分类要求的限制而存在极限位置。因此,硬间隔支持向量机所要解决的关键问题就是,如何从无穷多条直线(对应无穷多个分类器)中选择最优?

阅读更多

产品质量管理项目

摘要

本项目的核心任务是通过统计过程控制(SPC)方法,对某工厂生产的滚珠直径数据进行产品质量管理,评估产品工艺水平及其生产过程是否受控。统计过程控制作为一种基于概率统计的过程控制方法,自1924年由Shewhart博士提出控制图以来,已广泛应用于现代制造过程的质量控制中。本项目基于Matlab软件开发,对于收集到的数据,通过描述性统计分析、正态性检验、总体均值检验、工序能力指数计算与绘制均值控制图和方差控制图等多种方式,对数据进行全面分析,最终评估工艺水平及生产过程的受控状态。具体而言,首先,在数据收集过程中,结合实际数据与模拟数据,得到25组产品质量样本数据(每组至少5个样本);随后,通过描述性统计分析方法对数据进行宏观的认知,根据均值、方差、极差、直方图等指标对数据进行初步分析;接着又利用假设检验的方法,分别通过Pearson卡方检验与t检验等方法验证数据是否符合正态分布,并对其总体均值进行检验。基于对于正态总体及其均值、方差的检验合理性,最终计算并评估了数据的工序能力指数,同时绘制了均值控制图和方差控制图,以直观反映生产过程中的数据波动情况。通过多种方法的综合分析,最终得出了工厂生产的滚珠直径的工艺水平评价和生产过程的受控状态判断。

关键词: 产品质量管理、统计过程控制(SPC)、假设检验、Shewhart控制图、Matlab

项目概述

问题背景

现代产品质量管理主要有两个核心目标:第一,评价产品的工艺水平如何,即产品质量如何;第二,评价产品的生产过程是否受控,即产品可靠性如何。从现代质量控制的角度看,一方面要求产品质量好,另一方面还要求可靠性高。

统计过程控制(Statistical Process Control, SPC)是一种基于概率统计的过程控制方法。1924年美国贝尔实验室的Shewhart博士提出控制图,标志着产品统计质量控制的正式起点。作为现代质量管理的重要方法,SPC广泛应用于现代制造过程的质量控制。20实际80年代,国际上半导体制造过程已经普遍采用SPC技术提升产品合格率和可靠性。比如Motorola公司提出并在美国通用电器公司等广泛应用的6σ管理,其主要技术基础就是SPC理论。

生产过程是否处于统计受控状态,取决于生产过程是否存在异常因素导致产品质量的起伏变化。产品加工结果是否满足加工规范要求,反应的是工艺水平的高低;而工艺是否受控,反应的是生产过程是否存在异常因素。

项目任务

在本次项目中,需要收集批量产品质量数据,利用SPC方法对其进行管理,分析整体工艺水平并判断生产过程是否处于统计受控状态,具体而言可细分为如下任务:

  • 任务 1:收集或生成25组以上的数据,每组至少5个样本。

  • 任务2:根据均值,方差,极差,直方图等指标,对数据进行描述性统计分析。

  • 任务 3:对数据进行正态性检验与总体的均值检验。

  • 任务 4:计算数据工序能力指数并对其进行评估。

  • 任务 5:描绘均值控制图和方差控制图。

  • 任务 6:得出结论:工艺水平如何;生产过程是否处于统计受控状态。

项目过程

本项目完全基于Matlab代码实现SPC方法进行产品质量管理。

数据收集

本项目中的数据收集采用实际数据与模拟数据结合的方式,其中实际数据以书本7.4节的例题7.4.4[^1]为主要来源,在此基础上利用生成的模拟数据对其进行扩充,最终得到25组产品质量样本数据,每组中含有5个数据。

具体而言,本项目的问题情境为对工厂生产的滚珠直径(单位:$mm$)进行产品质量管理。书本上的例题提供了50个直径数据,将其作为扩充生成模拟数据的源数据source_data,即:

1
2
3
4
5
6
7
8
9
10
source_data=[15.0,15.8,15.2,15.1,15.9,
14.7,14.8,15.5,15.6,15.3,
15.0,15.6,15.7,15.8,14.5,
15.1,15.3,14.9,14.9,15.2,
15.9,15.0,15.3,15.6,15.1,
14.9,14.2,14.6,15.8,15.2,
15.2,15.0,14.9,14.8,15.1,
15.5,15.5,15.1,15.1,15.0,
15.3,14.7,14.5,15.5,15.0,
14.7,14.6,14.2,14.2,14.5];

设置扩充后的数据组数num_groups以及各组样本数据个数samples_per_groups:

1
2
num_groups = 25;
samples_per_group = 5;

两者相乘得到样本数据总数num_data_points:

1
num_data_points = num_groups * samples_per_group;

要对原始数据进行扩充,首先需要复制原始数据并添加随机扰动:

1
2
replicated_data = repmat(source_data, 1, ceil(num_data_points / length(source_data)));
perturbed_data = replicated_data(1:num_data_points) + 0.05 * randn(1, num_data_points);

接着使用插值生成更多数据点,并保留一位小数:

1
2
3
4
x = 1:length(perturbed_data);
xi = linspace(1, length(perturbed_data), num_data_points);
interpolated_data = interp1(x, perturbed_data, xi, 'spline');
interpolated_data = round(interpolated_data, 1);

最后将生成的模拟数据点重新组织为25组,每组5个数据,得到完整样本数据:

1
2
expanded_data = reshape(interpolated_data, samples_per_group, num_groups)';
data = expanded_data;

最终的样本数据如下表所示:

1 2 3 4 5
1 15.0000 14.6000 15.0000 15.1000 16.0000
2 14.9000 15.2000 15.5000 15.2000 14.7000
3 15.7000 14.7000 15.6000 15.2000 15.0000
4 14.2000 15.1000 15.5000 14.7000 14.6000
5 15.2000 15.5000 15.7000 14.9000 15.3000
6 14.7000 14.9000 15.1000 14.4000 14.3000
7 15.1000 15.6000 15.8000 14.8000 15.6000
8 15.9000 14.8000 15.1000 15.5000 14.3000
9 16.0000 15.3000 14.6000 15.3000 15.1000
10 15.2000 15.1000 15.1000 14.9000 14.6000
11 15.0000 14.8000 14.9000 15.1000 15.9000
12 14.9000 15.3000 15.5000 15.2000 14.7000
13 15.8000 14.8000 15.6000 15.3000 14.9000
14 14.1000 15.1000 15.4000 14.7000 14.6000
15 15.2000 15.5000 15.7000 14.9000 15.3000
16 14.6000 14.9000 15.0000 14.5000 14.3000
17 15.2000 15.6000 15.8000 14.9000 15.6000
18 15.8000 14.8000 15.1000 15.5000 14.2000
19 15.9000 15.3000 14.5000 15.2000 15.1000
20 15.2000 15.1000 15.0000 15.0000 14.5000
21 15.0000 14.7000 15.0000 15.1000 16.0000
22 14.9000 15.1000 15.6000 15.3000 14.6000
23 15.7000 14.9000 15.6000 15.4000 14.9000
24 14.2000 15.0000 15.5000 14.8000 14.7000
25 15.2000 15.4000 15.6000 14.9000 15.2000
阅读更多