浅析字母识别的算法
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代码 可以查看这里
相关文章推荐
- 用Python从零实现贝叶斯分类器的机器学习的教程
- My Machine Learning
- 机器学习---学习首页 3ff0
- Spark机器学习(一) -- Machine Learning Library (MLlib)
- 反向传播(Backpropagation)算法的数学原理
- 从SVD到PCA——奇妙的数学游戏
- 白化(Whitening):PCA vs. ZCA
- 关于SVM的那点破事
- 也谈 机器学习到底有没有用 ?
- TensorFlow人工智能引擎入门教程之九 RNN/LSTM循环神经网络长短期记忆网络使用
- TensorFlow人工智能引擎入门教程之十 最强网络 RSNN深度残差网络 平均准确率96-99%
- TensorFlow人工智能引擎入门教程所有目录
- 如何用70行代码实现深度神经网络算法
- 量子计算机编程原理简介 和 机器学习
- 近200篇机器学习&深度学习资料分享(含各种文档,视频,源码等)
- 已经证实提高机器学习模型准确率的八大方法
- 初识机器学习算法有哪些?
- 机器学习相关的库和工具
- 10个关于人工智能和机器学习的有趣开源项目
- 机器学习实践中应避免的7种常见错误