年前小编入手了两本机器学习的书籍,第一本是《机器学习与R语言》,基于R软件进行示例教学的;第二本是《机器学习实战》则是基于Python。想学习机器学习的朋友可以考虑入手这两本书:

关于《机器学习实战》,菜鸟团鲍志炜老师写了一些笔记,见
专栏从Python的Jupyter Notebook讲到机器学习实战,例如:
因此,本系列教程分享《机器学习与R语言》学习过程中的一些笔记。从我高中毕业之后,除了本科高数能考90分以外(学完也早忘了),小编的数学背景应该是0,所以笔记中如有错误,还请各位批评指正。
《机器学习与R语言》前两章算是预热。
第一章机器学习简介,介绍了机器学习的起源、使用和入门知识。简言之,机器学习和人的学习过程类似,从收集数据,推理数据到归纳数据发现规律,这一过程可概括为五个步骤:
第二章主要针对R初学者进行R和统计学相关基础知识的扫盲。
近邻分类的学习目的是分类,属于有监督的学习。
目的:近邻分类器就是把无标记的案例归类为与它们最相似的带有标记的案例所在的类。
应用:如果一个概念很难定义,但是当你看到它时就知道它是什么,这种情况近邻分类可能是适合的方法;但是,如果数据是噪声数据,组与组之间没有明确的界限,那么近邻算法可能难以确定类边界。
本文以常用的kNN算法为例:
kNN算法:用于分类的近邻方法可以通过k近邻(k-Nearest neighbor,kNN)算法举例说明。R class包中包含knn算法。
输入数据:训练数据及训练数据的标签、测试数据、k值,可以输出测序数据的预测标签。
k值的取值:假如有n个训练数据,可以取sqrt(n),最接近的奇数。另一种方法是基于各种测试数据来测试多个k值,并选择一个最佳的k值。除非数据的噪声非常大,否则打的训练数据集可以使用k值的选择并不那么重要。
数据的标准化:第一种是min-max标准化方法,将数据集中到0~1之内;第二种方法是z-score法。
分类数据应用于kNN:二分类变量例如性别,则数据转化为1(male), 0(female);多分类变量,0,1,2;如果是有序的,则编码为1,2,3。
示例数据在https://github.com/dataspelunking/MLwR,本例基于569例细胞活检案例,每个病例有32个特征信息,因变量y是癌症诊断结果,“M”为Malignant恶性,“B”为Benign良性,旨在利用kNN算法诊断乳腺癌。
# install.packages("class")
# install.packages("gmodels")
library(class) #knn函数
library(gmodels) #评估模型性能
library(dplyr)
##1.1读入数据
# import the CSV file
wbcd <- read.csv("./Rawdata/wisc_bc_data.csv", stringsAsFactors = FALSE)
str(wbcd)

# drop the id feature
wbcd <- wbcd[-1]
# table of diagnosis
table(wbcd$diagnosis)
# recode diagnosis as a factor
wbcd$diagnosis <- factor(wbcd$diagnosis, levels = c("B", "M"),
labels = c("Benign", "Malignant"))
# table or proportions with more informative labels
# round(table(wbcd$diagnosis) %>% prop.table()* 100 ,digits = 1)
table(wbcd$diagnosis) %>% prop.table()* 100
#Benign Malignant
#2.74165 37.25835
diagnosis是因变量y诊断结果良恶与否,其余30个特征都是数值型的,由10个细胞核特征的3种不同测量构成。看一下其中三个变量的特征
# summarize three numeric features
summary(wbcd[c("radius_mean", "area_mean", "smoothness_mean")])

image-20220313143422116
##1.2 标准化,这里采用min-max标准化数据
normalize <- function(x) {
return ((x - min(x)) / (max(x) - min(x)))
}
# test normalization function - result should be identical
# normalize(c(1, 2, 3, 4, 5))
# normalize(c(10, 20, 30, 40, 50))
# normalize the wbcd data
wbcd_n <- as.data.frame(lapply(wbcd[2:31], normalize)) #注意这里没有把标签纳入
# confirm that normalization worked
summary(wbcd_n$area_mean) # 0~1
## 1.3 准备训练数据和测试数据
# create training and test data
# training n =469, test n=100
wbcd_train <- wbcd_n[1:469, ]
wbcd_test <- wbcd_n[470:569,]
# create labels for training and test data
wbcd_train_labels <- wbcd[1:469, 1]
wbcd_test_labels <- wbcd[470:569, 1]
书中这里是如上取的,建议还是用随机抽样函数
sample()抽取
class包的knn()#输入train和test数据,train的label及k值(奇数),可以输出test数据的预测label
k = round(sqrt(469),digits = 1) # k=21.7,使用奇数21
wbcd_test_pred <- knn(train = wbcd_train, test = wbcd_test,
cl = wbcd_train_labels, k = 21)
table(wbcd_test_pred)
评估预测的wbcd_test_pred,和实际wbcd_test_labels中已知值的匹配程度如何。
# Create the cross tabulation of predicted vs. actual
CrossTable(x = wbcd_test_labels, y = wbcd_test_pred,
prop.chisq = FALSE)

上面这个交叉列联表看的累的话,试试这个:
library(gplots)
tab.0=table(wbcd_test_labels,wbcd_test_pred)
balloonplot(tab.0)

上面的模型发现有2个假阴性样本,但这个错误会导致2个恶性肿瘤被误认为是良性的,尽管准确率达到了98%,但2%错误的代价是高昂的,因此,需要提供模型的性能:
主要有两种策略:
##3.1 z-score法
# use the scale() function to z-score standardize a data frame
wbcd_z <- as.data.frame(scale(wbcd[-1])) #同样,不要纳入标签
# confirm that the transformation was applied correctly
summary(wbcd_z$area_mean)
# create training and test datasets
wbcd_train <- wbcd_z[1:469, ]
wbcd_test <- wbcd_z[470:569, ]
#输入train和test数据,train的label及k值(奇数),可以输出test数据的预测label
wbcd_test_pred <- knn(train = wbcd_train, test = wbcd_test,
cl = wbcd_train_labels, k = 21)
table(wbcd_test_pred)
# Create the cross tabulation of predicted vs. actual
CrossTable(x = wbcd_test_labels, y = wbcd_test_pred,
prop.chisq = FALSE)
然而这次分类的假阴性率反而上升至5%
这次更换k值
# try several different values of k
wbcd_train <- wbcd_n[1:469, ]
wbcd_test <- wbcd_n[470:569, ]
for(k in c(1,5,11,15,21,27)) {
wbcd_test_pred <- knn(train = wbcd_train, test = wbcd_test, cl = wbcd_train_labels, k=k)
CrossTable(x = wbcd_test_labels, y = wbcd_test_pred, prop.chisq=FALSE)
}
有一点像单细胞降维聚类取合适的dims和分辨率。
k值 | 假阴性数量 | 假阳性数量 | 错误分类的百分比 |
|---|---|---|---|
1 | 1 | 3 | 4% |
5 | 2 | 0 | 2% |
11 | 3 | 0 | 3% |
15 | 3 | 0 | 3% |
21 | 2 | 0 | 2% |
27 | 4 | 0 | 4% |
虽然分类器永远不会很完美,但是1NN算法能够避免一些假阴性结果,但是以增加假阳性结果为代价。然而值得注意的是,为了过于准确地预测测试数据来调整我们的方法是不明智的,毕竟,一组不同的100位病人的记录很可能与那些用来测量模型性能的记录有所不同。
如果需要确认一个学习算法能否推广到未来的数据,可能需要随机地创建/抽取几组 100或n 位病人的记录,重复测试这些结果。详见第十章。
kNN算法并没有进行任何的学习,它仅是一字不差的储存训练数据,然后利用距离函数将无标记的测试数据与训练数据进行匹配,然后贴上标签。在第4章朴素贝叶斯分类中,作者将研究使用概率来评估一个观测落入某些类别中的分类方法,比较该方法与kNN算法有何不同。在第9章中,将学习到一个与kNN很相似的算法,该方法把距离度量用于一个完全不同的学习任务。
- END -