您的位置:首页 > 其它

浅析字母识别的算法

2016-05-02 11:27 344 查看

前言

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

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

label: 从0至9的整数;

features: pixel001-pixel784, 分别对应28x28图片的每一个像素的位置;

每一个像素数据是0-255的整数,用来代表对应该像素点的亮度;

基本思路

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

这次比赛中所用到的图片是28x28的黑白图片,因此数据提供了784个特征用于模型训练。

了解数据

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

通过像素还原图片

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

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




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 显示

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

降维方法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 <-
## 调用线性SVM
train(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和小部分数据,我们已经得到相当不错的精度。

当然我们可以进一步探索,以提高模型的表度:

增加 PCA threshold 值,减小特征压缩的程度

用高阶SVM /高斯SVM, 神经网络,随机森林方法

用更加的数据进行训练

完整的R代码 可以查看这里
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息