[原创] 在树莓派3上使用微软ELL嵌入式学习库(2)

本文是上一篇文章的续文。
微软于2017年6月底发布了一个主要用于嵌入式系统(例如,树莓派,ARM Cortex-M0等)的机器学习库ELLEmbedded Learning Library嵌入式学习库)。
要在树莓派上使用pre-trained的模型,我们先要在PC上对其进行测试,这个测试说白了就是运行一些Python的demo程序看它们是否能正常工作。而上一篇文章,正是介绍了在Ubuntu PC上的准备工作——如果没有那些准备工作,你连测试的基础条件都不具备。
注:本文的所有操作,都是在台式机上运行的。

阅读更多

[原创] 在树莓派3上使用微软ELL嵌入式学习库(1)

微软于2017年6月底发布了一个主要用于嵌入式系统(例如,树莓派,ARM Cortex-M0等)的机器学习库ELLEmbedded Learning Library嵌入式学习库)。由于嵌入式设备的计算能力较弱,因此在这些设备上执行一些机器学习的任务——例如实时图像分类——通常速度很慢,所以在这种应用场景下,一般的策略是把请求发送到计算能力强大的云端服务器上去执行,嵌入式设备只作为和用户交互的终端,并不执行关键的计算任务。而微软发布的这个ELL,目标在于把云端的计算任务转移到嵌入式设备上,从而可以使得设备无需联网也能执行这些任务。这个目标看起来很诱人,但它要求ELL的计算速度很快、很节省资源,否则耗时将是不可接受的。

阅读更多

[原创] 执行ELL的demo程序cntkDemo.py时程序僵死的问题

OS:Ubuntu 14.04

在台式机上执行ELL的demo程序 cntkDemo.py 时,可能会遇到程序僵死的问题。
cntkDemo.py 这个程序会调用OpenCV,在一个GUI窗口中显示USB摄像头拍摄的实时视频流,而僵死的现象正是:执行到弹出GUI窗口显示摄像头拍摄的视频流的代码的时候,程序进入僵死状态,不能执行后续逻辑。此时,只能Ctrl+C终止掉程序。

阅读更多

[原创] 在Ubuntu上使用GParted来调整树莓派TF卡的分区大小

OS:Ubuntu 14.04 LTS

树莓派的操作系统存储在一张TF卡中,如果我们要备份它,只需要简单地在Ubuntu上使用如下命令即可:

sudo dd if=/dev/sdb of=~/raspberry_pi_os_backup

其中,/dev/sdb 是我的TF卡的设备名称。这样我们就可以把TF卡备份到 raspberry_pi_os_backup 这个文件中了。

阅读更多

[原创] 解决编译ELL的错误:undefined reference to `cblas_xxx'

OS:Ubuntu 14.04 LTS
在PC上编译ELL的时候,尽管你可能已经安装了所有ELL文档中要求的软件依赖,可能还是会遇到 undefined reference to `cblas_xxx' 的错误,如下:

0%] Built target documentation
[ 10%] Built target utilities
[ 11%] Built target math
[ 14%] Built target data
[ 23%] Built target emitters
[ 24%] Built target evaluators
[ 28%] Built target functions
[ 37%] Built target model
[ 39%] Built target predictors
[ 48%] Built target nodes
[ 52%] Built target trainers
[ 59%] Built target common
[ 60%] Built target testing
[ 61%] Linking CXX executable common_test
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Copy(int, float const*, int, float*, int)': BlasWrapper.cpp:(.text+0x31): undefined reference tocblas_scopy'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Copy(int, double const*, int, double*, int)': BlasWrapper.cpp:(.text+0x69): undefined reference tocblas_dcopy'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Asum(int, float const*, int)': BlasWrapper.cpp:(.text+0x92): undefined reference tocblas_sasum'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Asum(int, double const*, int)': BlasWrapper.cpp:(.text+0xba): undefined reference tocblas_dasum'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Nrm2(int, float const*, int)': BlasWrapper.cpp:(.text+0xf0): undefined reference tocblas_snrm2'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Nrm2(int, double const*, int)': BlasWrapper.cpp:(.text+0x118): undefined reference tocblas_dnrm2'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Scal(int, float, float*, int)': BlasWrapper.cpp:(.text+0x15b): undefined reference tocblas_sscal'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Scal(int, double, double*, int)': BlasWrapper.cpp:(.text+0x193): undefined reference tocblas_dscal'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Axpy(int, float, float const*, int, float*, int)': BlasWrapper.cpp:(.text+0x1d9): undefined reference tocblas_saxpy'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Axpy(int, double, double const*, int, double*, int)': BlasWrapper.cpp:(.text+0x221): undefined reference tocblas_daxpy'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Dot(int, float const*, int, float const*, int)': BlasWrapper.cpp:(.text+0x259): undefined reference tocblas_sdot'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Dot(int, double const*, int, double const*, int)': BlasWrapper.cpp:(.text+0x290): undefined reference tocblas_ddot'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Gemv(CBLAS_ORDER, CBLAS_TRANSPOSE, int, int, float, float const*, int, float const*, int, float, float*, int)': BlasWrapper.cpp:(.text+0x309): undefined reference tocblas_sgemv'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Gemv(CBLAS_ORDER, CBLAS_TRANSPOSE, int, int, double, double const*, int, double const*, int, double, double*, int)': BlasWrapper.cpp:(.text+0x37c): undefined reference tocblas_dgemv'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Gemm(CBLAS_ORDER, CBLAS_TRANSPOSE, CBLAS_TRANSPOSE, int, int, int, float, float const*, int, float const*, int, float, float*, int)': BlasWrapper.cpp:(.text+0x3f5): undefined reference tocblas_sgemm'
../math/libmath.a(BlasWrapper.cpp.o): In function ell::math::Blas::Gemm(CBLAS_ORDER, CBLAS_TRANSPOSE, CBLAS_TRANSPOSE, int, int, int, double, double const*, int, double const*, int, double, double*, int)': BlasWrapper.cpp:(.text+0x471): undefined reference tocblas_dgemm'
collect2: error: ld returned 1 exit status
make[2]: *** [libraries/common/common_test] Error 1
make[1]: *** [libraries/common/CMakeFiles/common_test.dir/all] Error 2
make: *** [all] Error 2

[原创] 在Ubuntu 14.04中安装gcc 6

成功编译ELL对gcc版本有要求,这而这一点在ELL的文档中并没有写。
gcc版本太低了是不行的,那么什么算版本低?反正我的gcc 4.8.4是不work的——使用低版本的gcc,你也可以照着文档完成很多步骤,但是到最后某一步,一定会遇到由于gcc版本低导致的问题,并且还没有直观的错误提示,查找问题源头可能会浪费你很多时间。

阅读更多

[原创] 升级Ubuntu 14.04上的Open MPI到 libmpi.so.12 版本

好好的为什么要折腾这个事?说来也是郁闷,在测试ELL的过程中,遇到了一个Open MPI package依赖的问题,它要用到 libmpi.so.12 这个动态链接库对应版本的Open MPI,而Ubuntu 14.04系统上,用 apt-get install libopenmpi-dev 安装上的是很旧的版本,因此只能升级系统里已经安装的Open MPI了。

阅读更多

[原创] Java Hadoop job合并输入的小文件(纯文本)

假设你的JAVA M-R job的输入文件是大量纯文本文件,而且每个文件都比较小(例如几百K),那么job运行起来之后会占用大量mapper数,导致Hadoop集群资源被过度消耗。这种情况可以通过合并输入文件来避免。

阅读更多

[原创] 为nginx服务器网站添加HTTPS/配置SSL证书

网站使用HTTPS的好处就不用多说了,在当今凶险的互联网环境下,使用HTTP越来越不安全,所以我也决定把网站转成HTTPS。使用HTTPS,首先你需要有一张SSL证书。
曾经,收费的SSL证书很贵,一般人玩不起;随着互联网的发展,免费的SSL证书越来越普及,谁都可以很容易获取到,所以HTTPS的个人网站也越来越多。
其中,现在最流行的就是使用可靠的数字证书认证机构Let's Encrypt提供的免费SSL证书。

阅读更多

[原创] 为nginx添加SSL支持模块

因为网站要加SSL证书的原因,把nginx折腾了一番,结果SSL相关的配置加到了nginx的配置文件中后,nginx竟然启动不起来了,用 systemctl status nginx 查看到的错误信息大致如下:

Failed to start SYSV: Nginx is an HTTP(S) server, HTTP(S) reverse ...

于是用如下命令测试问题所在:

/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

其中,/usr/local/nginx/sbin/nginx 是我的nginx安装后的可执行程序路径,/usr/local/nginx/conf/nginx.conf 是我的nginx主配置文件路径。

阅读更多

[原创] LaTeX for WordPress插件更新MathJax Server地址

MathJax是WordPress的LaTeX for WordPress插件调用的library,用于在WordPress页面上渲染显示完美的数学公式,配置过程可以参考这个链接。
从2017.04.30开始,MathJax CDN服务正式关闭(官方通知在这里),因此,如果我们原来在LaTeX for WordPress插件中配置的“MathJax Server”选择的是“MathJax CDN”,那么就会有问题了——服务将不再可用,这会导致数学公式在WordPress页面上不能被渲染显示。

阅读更多

[原创] 解决Java程序读写HDFS文件的错误:No FileSystem for scheme: hdfs

如果你在程序中(不是一个Hadoop job程序)有读写HDFS文件的逻辑,那么程序运行的时候可能会报下面的错:

Exception in thread "main" java.io.IOException: No FileSystem for scheme: hdfs
        at org.apache.hadoop.fs.FileSystem.getFileSystemClass(FileSystem.java:2676)
        at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2690)
        at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:94)
        at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2733)
        at org.apache.hadoop.fs.FileSystem$Cache.get(FileSystem.java:2715)
        at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:382)
        at org.apache.hadoop.fs.FileSystem.get(FileSystem.java:181)
        ......

[原创] 在树莓派上把文字转成语音(Text-To-Speech/TTS)

本文软硬件环境:
树莓派:3代 Model B V1.2,内存1GB
OS:Arch Linux ARM

有时候,我们需要在程序中添加文字转语音的功能,即通过某个程序或API,把输入的文字朗读出来,也就是通常所说的 text-to-speech(简写为TTS)。我尝试了一个简单的方案——使用Espeak来完成这个任务,在这里记录下来。

阅读更多