浅析字母识别的算法

来源:互联网 发布:vb书籍 编辑:程序博客网 时间:2024/06/06 08:16

前言

digit recogniser是另一个kaggle入门级别的比赛。这次,我将要介绍一下如何利用机器学习的算法实现图像识别。

在这次比赛里,我们要求训练一个模型从像素数据辨认出图片中的数字。比赛中用到的数据包含:

  1. label: 从0至9的整数;
  2. features: pixel001-pixel784, 分别对应28x28图片的每一个像素的位置;
  3. 每一个像素数据是0-255的整数,用来代表对应该像素点的亮度;

基本思路

我们知道图片是由像素(点)组成的矩阵,越多的像素可以呈现越清晰的画质。每一个像素由0-255的256个整数表示其不同的亮度,因此一个28x28的图片可以用一个28x28的矩阵来表达,矩阵中的数值也就是0-255的整数。然后彩色图片是个三元色的三个图层叠加而来,也就是说对于一个28x28的彩色图片,我们需要用到3x28x28个特征来表示。
这次比赛中所用到的图片是28x28的黑白图片,因此数据提供了784个特征用于模型训练。

了解数据

为了更加直观了解数据,我们可以用R的image语言画出像素数据所表达的图片。

通过像素还原图片

我们从数据中随机提取了100个样本。

display(test[sample(28000,100),],28)

28x28显示
28x28 显示

降维方法1

对于机器学习问题 784 个特征也许有点太多了。通过观察28x28的图片,我们可以发现数字相当的清楚,因此我们也许可以用更低的像素(比如14x14)来表达28x28的图片。通过这样的方法我们可以大幅地减少特征数量 (784 到 196)!
基本思路:用最亮的像素 (最大值)表达相邻4个像素。

reduceDim <- function(data){  pos <- matrix(1:784,28,28,byrow=T)  offset <- seq(1,28,2)  n <- 0  train.reduced <- data.frame(index=1:nrow(data))  if(!is.null(data$label)) train.reduced$label <- data$label  data$label <- NULL  for (i in offset){    for (j in offset){      px <- as.numeric(pos[i:(i+1),j:(j+1)])      px <- apply(data[,px],1,max)      index <- paste0('px',n)      n <- n+1      train.reduced[index] <- px    }  }  train.reduced$index <- NULL  return (train.reduced)}train.reduced <- reduceDim(train)test.reduced <- reduceDim(test)

让我们来观赛一个降维过后的图片:

display(test.reduced[sample(28000,100),],14)

14x14显示
14x14 显示

降维过后的数字仍然可以辨认!

降维方法2

除了上面提到手工的降维方法,我们还可以利用主要成分分析(PCA)来进行特征降维。主要成分分析是一个种压缩数据并投影到低维空间的方法。通过这种方法的压缩和还原会产生一定量的信息损失,然而十分明显的优点在于更加快速的模型训练。信息损失量可以保存的方差(variance retained)来表达,在没有特别情况下我可以用95%。在本组数据,我为了更大幅度的降维,选择90% variance retained。

library(caret)# thresh 即variance retained pea <- preProcess(rbind(train.reduced,test.reduced),method='pca',thresh=0.9)train.pca <- predict(pca,train.reduced)test.pca <- predict(pca,test.reduced)
## Call:## preProcess.default(x = rbind(train.reduced, test.reduced), method =##  "pca", thresh = 0.9)## ## Created from 70000 samples and 101 variables## Pre-processing: principal component signal extraction, scaled, centered ## ## PCA needed 47 components to capture 90 percent of the variance.

运用PCA,我们成功地把特征进一步从196减少到47!

运用线性SVM训练模型

为了演示,我只提取了500行数据训练。

## 交叉验证ctrl <- trainControl(method='cv',number = 10)## 提取样本inTrain <- sample(42000,500)## 记录运行时间run_time <- system.time(fit <-## 调用线性SVMtrain(factor(label[inTrain])~.,data=train.pca[inTrain,],            trControl = ctrl,            method='svmLinear'))print (fit)
## Support Vector Machines with Linear Kernel ## ## 500 samples##  46 predictor##  10 classes: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ## ## No pre-processing## Resampling: Cross-Validated (10 fold) ## ## Summary of sample sizes: 449, 452, 449, 449, 451, 450, ... ## ## Resampling results## ##   Accuracy   Kappa     Accuracy SD  Kappa SD  ##   0.8219855  0.801539  0.03704343   0.04130649## ## Tuning parameter 'C' was held constant at a value of 1## 

总结

利用简单的线性SVM和小部分数据,我们已经得到相当不错的精度。
当然我们可以进一步探索,以提高模型的表度:

  1. 增加 PCA threshold 值,减小特征压缩的程度
  2. 用高阶SVM /高斯SVM, 神经网络,随机森林方法
  3. 用更加的数据进行训练

完整的R代码 可以查看这里

0 0
原创粉丝点击