Overview1.加载数据2.处理数据3.构建模型4.编译并训练模型 Overview 本篇我们来记录一下怎么使用TensorFlow2.0当中的Keras模块来进行CNN图片分类。 1.加载数据 我们用经典的猫狗分类数据集来做这次图片分类。 import os import numpy as np import matplotlib.pyplot as plt import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D from tensorflow.keras.preprocessing.image import ImageDataGenerator # 下载数据 _URL = 'https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip' path_to_zip = tf.keras.utils.get_file('cats_and_dogs.zip', origin=_URL, extract=True) PATH = os.path.join(os.path.dirname(path_to_zip), 'cats_and_dogs_filtered') 统计下载到本地的数据： train_dir = os.path.join(PATH, 'train') validation_dir = os.path.join(PATH, 'validation') train_cats_dir = os.path.join(train_dir, 'cats') # 训练集猫图 train_dogs_dir = os.path.join(train_dir, 'dogs') # 训练集狗图 validation_cats_dir = os.path.join(validation_dir, 'cats') # 验证集猫图 validation_dogs_dir = os.path.join(validation_dir, 'dogs') # 验证集狗图 num_cats_train = len(os.listdir(train_cats_dir)) num_dogs_train = len(os.listdir(train_dogs_dir)) num_cats_val = len(os.listdir(validation_cats_dir)) num_dogs_val = len(os.listdir(validation_dogs_dir)) total_train = num_cats_train + num_dogs_train total_val = num_cats_val + num_dogs_val 2.处理数据 如果直接拿训练集去训练，会遇到过拟合问题，所以我们需要对训练集进行数据增强。图片的数据增强是很简单的，有水平或垂直翻转，旋转，缩放等等方式。 batch_size = 128 epochs = 15 IMG_HEIGHT = 150 IMG_WIDTH = 150 train_image_generator = ImageDataGenerator( rescale=1./255, rotation_range=45, width_shift_range=.15, height_shift_range=.15, horizontal_flip=True, zoom_range=0.5 ) # train_image_generator = ImageDataGenerator(rescale=1./255) validation_image_generator = ImageDataGenerator(rescale=1./255) 读取图片： train_data_gen = train_image_generator.flow_from_directory(batch_size=batch_size, directory=train_dir, shuffle=True, target_size=(IMG_HEIGHT, IMG_WIDTH), class_mode='binary') val_data_gen = validation_image_generator.flow_from_directory(batch_size=batch_size, directory=validation_dir, target_size=(IMG_HEIGHT, IMG_WIDTH), class_mode='binary') 3.构建模型 我们用tensorflow.keras.models.Sequential来顺序堆叠卷积神经网络，同时加上Dropout层来防止过拟合。 model = Sequential([ Conv2D(16, 3, padding='same', activation='relu', input_shape=(IMG_HEIGHT, IMG_WIDTH ,3)), MaxPooling2D(), Conv2D(32, 3, padding='same', activation='relu'), MaxPooling2D(), Conv2D(64, 3, padding='same', activation='relu'), MaxPooling2D(), Dropout(0.2), # dropout层是用来防止过拟合的 Flatten(), Dense(512, activation='relu'), Dense(1) ]) 查看一下网络结构： model.summary() 显示如下： Model: "sequential" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d (Conv2D) (None, 150, 150, 16) 448 _________________________________________________________________ max_pooling2d (MaxPooling2D) (None, 75, 75, 16) 0 _________________________________________________________________ conv2d_1 (Conv2D) (None, 75, 75, 32) 4640 _________________________________________________________________ max_pooling2d_1 (MaxPooling2 (None, 37, 37, 32) 0 _________________________________________________________________ conv2d_2 (Conv2D) (None, 37, 37, 64) 18496 _________________________________________________________________ max_pooling2d_2 (MaxPooling2 (None, 18, 18, 64) 0 _________________________________________________________________ dropout (Dropout) (None, 18, 18, 64) 0 _________________________________________________________________ flatten (Flatten) (None, 20736) 0 _________________________________________________________________ dense (Dense) (None, 512) 10617344 _________________________________________________________________ dense_1 (Dense) (None, 1) 513 ================================================================= Total params: 10,641,441 Trainable params: 10,641,441 Non-trainable params: 0 4.编译并训练模型 model.compile(optimizer='adam', loss=tf.keras.losses.BinaryCrossentropy(from_logits=True), metrics=['acc']) history = model.fit( train_data_gen, steps_per_epoch=total_train // batch_size, epochs=epochs, validation_data=val_data_gen, validation_steps=total_val // batch_size ) 这里，选择优化算法时，一般情况下，无脑选择adam即可。 如果运行训练时报如下错误： ImportError: Could not import PIL.Image. The use of `load_img` requires PIL. 那么安装pillow包即可： pip install pillow 如果运行正常，显示如下： Epoch 1/15 15/15 [==============================] - 31s 2s/step - loss: 0.9137 - acc: 0.4995 - val_loss: 0.6909 - val_acc: 0.5011 Epoch 2/15 15/15 [==============================] - 30s 2s/step - loss: 0.6883 - acc: 0.5016 - val_loss: 0.6954 - val_acc: 0.6205 Epoch 3/15 15/15 [==============================] - 30s 2s/step - loss: 0.6933 - acc: 0.5123 - val_loss: 0.6849 - val_acc: 0.4911 Epoch 4/15 15/15 [==============================] - 30s 2s/step - loss: 0.6825 - acc: 0.5037 - val_loss: 0.6637 - val_acc: 0.6105 Epoch 5/15 15/15 [==============================] - 30s 2s/step - loss: 0.6613 - acc: 0.5716 - val_loss: 0.6391 - val_acc: 0.6529 Epoch 6/15 15/15 [==============================] - 30s 2s/step - loss: 0.6439 - acc: 0.5946 - val_loss: 0.6150 - val_acc: 0.6641 Epoch 7/15 15/15 [==============================] - 31s 2s/step - loss: 0.6196 - acc: 0.6167 - val_loss: 0.6006 - val_acc: 0.6641 Epoch 8/15 15/15 [==============================] - 31s 2s/step - loss: 0.6096 - acc: 0.6282 - val_loss: 0.6135 - val_acc: 0.6708 Epoch 9/15 15/15 [==============================] - 31s 2s/step - loss: 0.6063 - acc: 0.6325 - val_loss: 0.5719 - val_acc: 0.6908 Epoch 10/15 15/15 [==============================] - 30s 2s/step - loss: 0.6040 - acc: 0.6485 - val_loss: 0.6070 - val_acc: 0.6920 Epoch 11/15 15/15 [==============================] - 30s 2s/step - loss: 0.5804 - acc: 0.6688 - val_loss: 0.5853 - val_acc: 0.6998 Epoch 12/15 15/15 [==============================] - 30s 2s/step - loss: 0.5908 - acc: 0.6683 - val_loss: 0.5668 - val_acc: 0.6362 Epoch 13/15 15/15 [==============================] - 30s 2s/step - loss: 0.5828 - acc: 0.6667 - val_loss: 0.5698 - val_acc: 0.7054 Epoch 14/15 15/15 [==============================] - 31s 2s/step - loss: 0.5673 - acc: 0.6976 - val_loss: 0.5514 - val_acc: 0.7054 Epoch 15/15 15/15 [==============================] - 30s 2s/step - loss: 0.5627 - acc: 0.6971 - val_loss: 0.5685 - val_acc: 0.7154 查看模型训练过程： acc = history.history['acc'] val_acc = history.history['val_acc'] loss=history.history['loss'] val_loss=history.history['val_loss'] epochs_range = range(epochs) plt.figure(figsize=(8, 8)) plt.subplot(1, 2, 1) plt.plot(epochs_range, acc, label='Training Accuracy') plt.plot(epochs_range, val_acc, label='Validation Accuracy') plt.legend(loc='lower right') plt.title('Training and Validation Accuracy') plt.subplot(1, 2, 2) plt.plot(epochs_range, loss, label='Training Loss') plt.plot(epochs_range, val_loss, label='Validation Loss') plt.legend(loc='upper right') plt.title('Training and Validation Loss') plt.show() 可以看到并没有过拟合，训练还是比较满意的。 本篇文章主要参考了TensorFlow2.0官方文档，Image classification。
机器学习项目服务器上线部署全流程记录
Overview1.Java端1.1 安装JDK1.81.2 安装Tomcat71.2.1 配置Tomcat7启动内存1.3 检查安装php和Apache21.4 设置Apache2反向代理1.5 安装MySQL5.71.6 安装配置phpmyadmin2.Perl后台2.1 设置Apache2 CGI2.2 Perl相关模块安装2.3 gearman消息队列安装3. Python相关安装4. R语言及相关包安装 Overview 我们团队完整的机器学习项目已经做了两个了，分别是Bastion4和Bastion6。之前两个项目上线部署的记录过于片段化，针对现在马上要做完的Bastion3项目，我们在此完整记录搭建服务器各种环境的全部流程，以备不时之需。 完整的项目基本分为三大部分：Java处理业务逻辑；Perl后台消息队列；R机器学习模型预测。每个大部分还有很多细节，我们会在每部分都详细记录。 新申请的云服务器预装的仍然是Ubuntu16.04LTS发行版的Linux系统。 1.Java端 Java端负责将用户提交的任务信息提交至后台Perl服务器并记录在MySQL数据库中。因此这部分会安装JDK1.8，Tomcat7和MySQL5.7。 1.1 安装JDK1.8 安装JDK1.8，用apt命令很方便，不用单独下载解压。命令如下： sudo apt-get install software-properties-common -y sudo add-apt-repository ppa:webupd8team/java -y sudo apt-get update sudo apt-get install oracle-java8-installer oracle-java8-set-default -y 安装完成之后，JDK1.8会被安装在/usr/lib/jvm/java-8-oracle中，在/etc/profile或者~/.bashrc中配置JAVA_HOME变量 (我用的是~/.bashrc文件)： export JAVA_HOME=/usr/lib/jvm/java-8-oracle 安装好之后，需要以下命令使配置生效： source ~/.bashrc 1.2 安装Tomcat7 使用以下的命令安装Tomcat7: sudo apt-get install tomcat7 安装过程中，可能会报如下的错误(即使你已经配置好了JAVA_HOME): Jul 09 16:52:16 bastiondb systemd[1]: Starting LSB: Start Tomcat.... Jul 09 16:52:16 bastiondb tomcat7[6413]: * no JDK or JRE found - please...E Jul 09 16:52:16 bastiondb systemd[1]: tomcat7.service: Control process e...1 Jul 09 16:52:16 bastiondb systemd[1]: Failed to start LSB: Start Tomcat.. Jul 09 16:52:16 bastiondb systemd[1]: tomcat7.service: Unit entered fail.... Jul 09 16:52:16 bastiondb systemd[1]: tomcat7.service: Failed with resul.... Hint: Some lines were ellipsized, use -l to show in full. dpkg: error processing package tomcat7 (--configure): subprocess installed post-installation script returned error exit status 1 Errors were encountered while processing: tomcat7 E: Sub-process /usr/bin/dpkg returned an error code (1) 出现这个错误，说明tomcat7已经装好了，但是由于tomcat在启动时找不到JAVA_HOME的路径，所以报错。查看/etc/default/tomcat7，会发现下面这行： #JAVA_HOME=/usr/lib/jvm/openjdk-6-jdk 去掉注释，并改为我们自己的JAVA_HOME路径： JAVA_HOME=/usr/lib/jvm/java-8-oracle 重新运行安装命令： sudo apt-get install tomcat7 安装成功... 安装好之后，tomcat7已经在运行了，使用下面命令查看： ps aux | grep tomcat 用下面的命令启动/停止/重启Tomcat7了: sudo service tomcat7 start/stop/restart 但是现在还有一个问题，Tomcat7的端口是8080，访问的时候必须在地址后面加上:8080，这样看起来不太和谐。由于Apache已经占用了80端口，所以我们采用Apache反向代理转发Tomcat请求的方式来解决这个问题。 1.2.1 配置Tomcat7启动内存 Tomcat启动内存不大，在网站数据量增多的情况下，就会在网页访问时报错，很难根据错误信息推测到这里。我们提前增大Tomcat的启动内存。 修改/usr/share/tomcat7/bin/catalina.sh文件 sudo vim /usr/share/tomcat7/bin/catalina.sh 可以看到： # OS specific support. $var _must_ be set to either true or false. cygwin=false darwin=false os400=false case "`uname`" in CYGWIN*) cygwin=true;; Darwin*) darwin=true;; OS400*) os400=true;; 在这段前面添加： JAVA_OPTS="-Xmx4096m" 就可以将tomcat启动内存增加为4G，保存并重启tomcat，就可以了。 下面的内容选择性安装，如果没有特殊需求，最好不要修改 默认的tomcat工作主目录为/var/lib/tomcat6/，网站目录为/var/lib/tomcat6/webapps，如果你的文章会产生大量文件，并且需要存放在网站的目录下，那这个目录就不太合适，因为这个目录通常占用的是系统盘空间。 假设你有一个新的扩展盘，目录为/my_extended_disk，在上面创建一个目录为tomcatWebapps，并想把这个目录，当做你的tomcat网站目录，修改/etc/tomcat7/server.xml sudo vim /etc/tomcat7/server.xml 把 <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> 修改为 <Host name="localhost" appBase="/my_extended_disk/tomcatWebapps" unpackWARs="true" autoDeploy="true"> 然后重启服务器，就可以了。 1.3 检查安装php和Apache2 一般来说，装好的Ubuntu 16.04系统都会默认装好php和Apache2，但配置使用之前最好还是检查一下。 使用下面命令检查php： php -v 如果已经安装，大概会显示下面的内容： PHP 7.0.32-0ubuntu0.16.04.1 (cli) ( NTS ) Copyright (c) 1997-2017 The PHP Group Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies with Zend OPcache v7.0.32-0ubuntu0.16.04.1, Copyright (c) 1999-2017, by Zend Technologies 说明安装了php 7.0。如果没装的话，用下面的命令安装： sudo apt-get install php7.0 在Ubuntu 16.04中，直接用 sudo apt-get install php 默认安装的也是php7.0版本。 使用下面命令检查Apache2： apache2 -v 如果已经安装，大概会显示下面的内容： Server version: Apache/2.4.18 (Ubuntu) Server built: 2018-04-18T14:53:04 说明没装的话，用下面的命令安装： sudo apt-get install apache2 注意：如果php和Apache2都没有安装的情况下，安装顺序一定要先装php，在装Apache2，如果顺序反了，可能会导致Apache2服务器不能识别php页面，在你访问这些页面的时候，直接显示页面的代码，而不是页面本身。 参见 php页面不能被解析成网页，而是直接显示了页面代码。 1.4 设置Apache2反向代理 Apache2默认是随系统安装的，但有时候为了快速安装，去掉了也有可能。由于Apache2是随系统自动启动的，如果Apache2已经安装了并且没有人主动关闭的话，使用： ps aux | grep apache2 就应该看到进程信息，如果没看到，用下面的命令安装： sudo apt-get install apache2 安装成功之后，使用服务器的地址(比如bastion3.erc.monash.edu)访问，就应该看到Apache2的欢迎界面。 如果安装成功，但是网址却无法访问，说明80端口没开，联系管理员，打开这个端口。 修改Apache2配置文件： sudo vim /etc/apache2/apache2.conf 在文件末尾添加以下内容： ProxyPass / http://bastion3.erc.monash.edu:8080/ ProxyPassReverse / http://bastion3.erc.monash.edu:8080/ 可以让Apache2把http://bastion3.erc.monash.edu请求转发到http://bastion3.erc.monash.edu:8080/由tomcat7处理。如果你在Apache2中有一个网站cgi-bin，你访问http://bastion3.erc.monash.edu/cgi-bin时，就想访问Apache2下的cgi-bin，而不是转成http://bastion3.erc.monash.edu:8080/cgi-bin由tomcat7处理，那么改成这样就可以了： ProxyPass /phpmyadmin ! ProxyPass /cgi-bin ! ProxyPass / http://bastion3.erc.monash.edu:8080/ ProxyPassReverse / http://bastion3.erc.monash.edu:8080/ 注意：这里同时写了一个phpmyadmin的配置，是因为我们会使用phpmyadmin管理和访问数据库。参考1.6小节的内容。 重启Apache2服务： sudo service apache2 restart 如果报错： Job for apache2.service failed because the control process exited with error code. See "systemctl status apache2.service" and "journalctl -xe" for details. 根据提示，使用 systemctl status apache2.service 查看错误信息： Jul 09 17:15:56 bastiondb apache2[7914]: * The apache2 configtest failed. Jul 09 17:15:56 bastiondb apache2[7914]: Output of config test was: Jul 09 17:15:56 bastiondb apache2[7914]: AH00526: Syntax error on line 223 o Jul 09 17:15:56 bastiondb apache2[7914]: Invalid command 'ProxyPass', perhap Jul 09 17:15:56 bastiondb apache2[7914]: Action 'configtest' failed. Jul 09 17:15:56 bastiondb apache2[7914]: The Apache error log may have more Jul 09 17:15:56 bastiondb systemd[1]: apache2.service: Control process exite Jul 09 17:15:56 bastiondb systemd[1]: Failed to start LSB: Apache2 web serve Jul 09 17:15:56 bastiondb systemd[1]: apache2.service: Unit entered failed s Jul 09 17:15:56 bastiondb systemd[1]: apache2.service: Failed with result 'e 发现Apache2不能识别新添加的ProxyPass，导致重启失败。这是因为Apache2的代理模块proxy_http未启用，使用下面命令： sudo a2enmod proxy_http 重新启动Apache2： sudo service apache2 restart 成功...这时候再输入服务器的地址，即可访问到tomcat的默认项目了，后面不用加:8080。 1.5 安装MySQL5.7 先更新一下系统，再用apt-get命令直接安装： sudo apt-get update sudo apt-get install mysql-server 安装过程会让选择yes/no,选yes；还有就是设置root用户密码。 安装完成可以查看是不是安装好了,即查看MySQL的状态： sudo service mysql status 显示如下即可： ?.mysql.service - MySQL Community Server Loaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2018-03-19 14:35:03 UTC; 27s ago Main PID: 17432 (mysqld) CGroup: /system.slice/mysql.service ?..17432 /usr/sbin/mysqld Mar 19 14:35:02 bastion3 systemd[1]: Starting MySQL Community Server... Mar 19 14:35:03 bastion3 systemd[1]: Started MySQL Community Server. 安装好之后，可以用以下命令启动/停止/重启： sudo service mysql stop/stop/restart 本项目的数据的形式和之前项目的很相似，所以可以将之前的Bastion6项目数据库文件导出，然后再导入本项目。 导出命令： mysqldump -uroot -p bastion6 > bastion6.sql 回车之后输入数据库密码即可。 将bastion6.sql内容修改为自己需要的： CREATE DATABASE IF NOT EXISTS bastion3; USE bastion3; DROP TABLE IF EXISTS `job`; CREATE TABLE `job` ( `jobID` int(100) NOT NULL AUTO_INCREMENT, `jobName` varchar(256) NOT NULL, `orgnization` varchar(1000) , `email` varchar(100) NOT NULL, `status`int(1) NOT NULL, `createTime` datetime NOT NULL, `startTime` datetime , `endTime` datetime , `sequence` longtext NOT NULL, `sequenceNumber` int(10) NOT NULL, PRIMARY KEY (`jobID`) ) DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `predictresult`; CREATE TABLE `predictresult` ( `jobID` int(100) NOT NULL AUTO_INCREMENT, `jobName` varchar(256) NOT NULL, `predictionResult` longtext, PRIMARY KEY (`jobID`) ) DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `pssm`; CREATE TABLE `pssm` ( `id` int(100) NOT NULL AUTO_INCREMENT, `seq` varchar(10000), `output` varchar(500) , PRIMARY KEY (`id`) ) DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `downloadInfo`; CREATE TABLE `downloadInfo` ( `id` int(100) NOT NULL AUTO_INCREMENT, `type` varchar(10000), `count` varchar(500) , PRIMARY KEY (`id`) ) DEFAULT CHARSET=utf8; INSERT INTO `downloadInfo` VALUES (1,'originalData','0'),(2,'independentData','0'),(3,'predictData','0'); 然后登录数据库: mysql -u root -p 回车之后输入密码。 将上面的SQL命令输入，回车即可创建完整的数据库表。 至此，Java部分安装配置就算完成了。 1.6 安装配置phpmyadmin 命令行查看和管理MySQL还是有点不方便，所以我们这里安装一个phpmyadmin，就可以使用web界面查看和操作数据库。 这时候直接使用网址+phpmyadmin，浏览器会显示找不到phpmyadmin。那是因为apache2默认的网站路径是/var/www/html，而不是/var/www，编辑/etc/apache2/sites-enabled/000-default.conf： sudo vim /etc/apache2/sites-enabled/000-default.conf 把DocumentRoot /var/www/html修改为DocumentRoot /var/www 重启apache2，重新访问，就可以了。 安装phpmyadmin sudo apt-get install phpmyadmin 安装过程中，会弹出一个Configuring phpmyadmin框，让你选择要运行phpmyadmin的服务器，默认是apache2，还可以选择lighttpd，因为我们之前安装的web服务器是apache2，所以直接敲回车就行了。 然后安装一阵子继续弹出一个Configuring phpmyadmin框，提示你是否需要配置数据库，毕竟phpmyadmin本身就是管理数据库的，不配置好数据库，也就没有安装的意义了，默认选择的是Yes，回车，会转到新的界面让你输入密码，也就是刚才安装MySQL时设置的密码，输入之后敲回车确认，再重复确认密码，完成安装。 安装完成之后，发现在apache2的网站目录/var/www下，并没有多出来一个phpmyadmin，这是因为Ubuntu系统在安装phpmyadmin时，默认安装在了/usr/share/下: ls /usr/share/ 就可以看到里面有phpmyadmin。 我们直接创建一个软连接： sudo ln -s /usr/share/phpmyadmin /var/www/phpmyadmin 这样就可以在/var/www下访问到phpmyadmin。 如果发现虽然能访问phpmyadmin了，但是浏览器直接显示了代码，而不是网页，说明apache2没有自动安装解析php的包。 先用下面的命令看看你装的php版本： php --version 如果是php7.0，那么安装下面的包： sudo apt-get install libapache2-mod-php7.0 然后重启apache2，现在应该可以访问到正常的网页了。具体原因，参见php页面不能被解析成网页，而是直接显示了页面代码。 用户名是root，密码是MySQL设置的密码。 注意： 由于phpmyadmin网站暴露在公网之后，可能会招到攻击，比如使用脚本破解密码等，因此我们需要配置一下白名单，中只允许指定IP访问。修改/etc/apache2/apache2.conf，在里面添加: Options Indexes FollowSymLinks Includes ExecCGI AllowOverride All # Key configuration for white list Order Deny,Allow Allow from xx.xx.xx.xx Allow from xx.xx.xx.xy Deny from All 其中，/var/www/phpmyadmin为phpmyadmin网站路径，xx.xx.xx.xx和xx.xx.xx.xy为允许访问的IP地址。 2.Perl后台 Perl的主要作用是它的消息队列以及和Java通讯的CGI模块。因此需要配置Apache2 CGI以及安装相应的Perl模块。 2.1 设置Apache2 CGI 在安装CGI模块之前，最好先将make安装好： sudo apt-get install make 然后安装Perl的CGI模块，推荐使用cpan命令安装 (一定要用sudo权限打开)： 先打开cpan： sudo cpan 然后输入下面的命令: install CGI 下面修改CGI程序的根目录： sudo vim /etc/apache2/apache2.conf 将配置文件中对应的地方改为如下： Options Indexes FollowSymLinks AllowOverride None Require all granted 在/var/www/cgi-bin目录中新建一个cgi_test.pl文件，以创建一个Perl CGI网站，文件内容为： #!/usr/bin/perl -w use warnings; use CGI qw(:standard); #! must use 'my' to define a variable print header; my $now_string = localtime(); print "Hello, CGI using Perl! It's $now_string NOW! "; 为此文件添加执行权限： sudo chmod +x /var/www/cgi-bin/cgi_test.pl 在命令行中执行此文件： sudo perl /var/www/cgi-bin/cgi_test.pl 如果之前的设置正确，则会显示以下内容： Content-Type: text/html; charset=ISO-8859-1 Hello, CGI using Perl! It's Tue Mar 20 14:17:15 2018 NOW! 至此，虽然可以在命令行中运行此程序，但是还不能作为服务器远程访问。我们需要做以下配置，让Apache2对Perl支持： sudo vim /etc/apache2/sites-enabled/000-default.conf 将下面的内容： ... ServerAdmin webmaster@localhost DocumentRoot /var/www ... ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined 修改为： ... ServerAdmin webmaster@localhost DocumentRoot /var/www ScriptAlias /cgi-bin/ /var/www/cgi-bin/ AllowOverride all Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all AddHandler cgi-script .cgi .pl ... ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined 在Apache中启用CGI模块。注意 VirtualHost *:80这里的端口号尽量不要改动，因为使用网址或者ip地址访问，不加端口号的话，默认就是访问80端口号，如果改了端口号，就得显示加上。 默认情况下，这个模块是没有开启的，这点可以用以下命令确认： ls -l /etc/apache2/mods-enabled/ | grep cgi 显示为空表示当前启用的与CGI相关的模块为空。用下面的命令查看有哪些模块可以被启用： ls -l /etc/apache2/mods-available/ | grep cgi 显示如下： -rw-r--r-- 1 root root 74 Mar 19 2016 authnz_fcgi.load -rw-r--r-- 1 root root 115 Mar 19 2016 cgid.conf -rw-r--r-- 1 root root 60 Mar 19 2016 cgid.load -rw-r--r-- 1 root root 58 Mar 19 2016 cgi.load -rw-r--r-- 1 root root 89 Mar 19 2016 proxy_fcgi.load -rw-r--r-- 1 root root 89 Mar 19 2016 proxy_scgi.load 这样，我们在mods-enabled中创建软连接，指向mods-available中的cgid.*文件： sudo ln -s /etc/apache2/mods-available/cgid.load /etc/apache2/mods-enabled/ sudo ln -s /etc/apache2/mods-available/cgid.conf /etc/apache2/mods-enabled/ 重启Apache服务器： sudo service apache2 restart 此时，如果在浏览器中访问：http://bastion3.erc.monash.edu/cgi-bin/cgi_test.pl应该会显示： Hello, CGI using Perl! It's Tue Mar 20 14:17:15 2018 NOW! 这样就算成功了。 2.2 Perl相关模块安装 在安装这部分模块之前，最好保证gcc和g++两个程序已经安装好了，如果没有安装好，那么按照以下命令安装： sudo apt-get install gcc sudo apt-get install g++ Perl模块仍然要使用sudo cpan命令安装，然后依次输入以下命令： install Storable install DBI install IO::All install Bio::SeqIO install Bio::Seq install Capture::Tiny install SOAP::Transport::HTTP install MIME::Lite install Mail::Sendmail 2.3 gearman消息队列安装 当前最新版的gearman是gearmand-1.1.12。我们执行下面几步，先将其下载到本地主文件夹，并解压缩。 cd ~ sudo apt-get update wget https://launchpad.net/gearmand/1.2/1.1.12/+download/gearmand-1.1.12.tar.gz tar zxvf gearmand-1.1.12.tar.gz cd gearmand-1.1.12/ 进入gearmand-1.1.12文件夹后，如果直接运行 ./configure 就会报缺少如下几个依赖包错误： configure: error: could not find boost configure: error: Could not find a version of the library configure: error: could not find gperf configure: error: Unable to find libevent configure: error: Unable to find libuuid 所以，我们先将这些依赖都安装好： sudo apt-get install libboost-dev sudo apt-get install libboost-all-dev sudo apt-get install gperf sudo apt-get install libevent-dev sudo apt-get install uuid-dev 安装好之后，如果没有错误，则运行： ./configure 然后仍在gearmand-1.1.12文件夹下运行下面两条命令，编译时间比较长： sudo make sudo make install 这个过程中如果出现了错误，就运行下面的命令清除一下之前编译产生的可执行文件以及object文件(即扩展名为o的文件)： sudo make clean 继续重新安装编译： ./configure sudo make sudo make install 没有错误的话，就安装gearman的job server： sudo apt-get install gearman-job-server 安装好以后，运行一下gearman: gearman -d 会提示错误： gearman: error while loading shared libraries: libgearman.so.8: cannot open shared object file: No such file or directory 这表示找不到libgearman.so.8所在的目录。这时我们打开/etc/ld.so.conf文件： sudo vim /etc/ld.so.conf 添加一句话: include /usr/local/lib 保存退出，并执行下面这句： sudo /sbin/ldconfig 这样就不会出错了。 启动一下job server： gearmand -d 报错如下： gearmand: Could not open log file "/usr/local/var/log/gearmand.log", from "/home/ubuntu/gearmand-1.1.12", switching to stderr. (No such file or directory) 我们这样解决：在/usr/local/下面新建var子目录，进去，新建log子目录，再进去，新建文件gearmand.log。这样就没有问题了。 用sudo权限运行下面的命令： sudo gearmand -d -L 127.0.0.1 -p 4730 -d表示daemon，在后台运行； -L表示监听的ip，默认是localhost； -p表示监听的端口号port，默认是4730。 此时，使用下面的命令，即可查看gearman当前状态： sudo lsof -i:4730 如果显示如下，就表示成功安装： COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME gearmand 27831 gearman 10u IPv4 320614 0t0 TCP localhost:4730 (LISTEN) 这样gearman在ubuntu16.04上面就安装成功了。 至此，我们还需要安装三个Perl模块： Gearman::Server Gearman::Client Gearman::Worker 在安装Gearman::Server的时候，需要依赖Net::SSLeay,IO::Socket::SSL和Gearman::Util,而安装Net::SSLeay的时候，如果没有libssl-dev这个系统包，是安装不上Net::SSLeay的。所以我们必须要先安装好libssl-dev。 sudo apt-get install libssl-dev 然后必须按顺序依次安装Net::SSLeay，顺序不能乱: 继续打开cpan： sudo cpan 然后 install Net::SSLeay install IO::Socket::SSL install Gearman::Util 依次安装： install Gearman::Server install Gearman::Client install Gearman::Worker 都安装后之后，可以重启一下机器。 启动之后，用如下命令观察4730端口，查看gearman的job server是否已经启动(gearmand -d这条命令是否生效)： sudo lsof -i:4730 显示如下： COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME gearmand 907 gearman 10u IPv4 21414 0t0 TCP localhost:4730 (LISTEN) 可以知道，这个server是开机自启动的。 至此，gearman消息队列的安装就算完成了。 每次重启服务器，都需要重启worker脚本。worker和client脚本都会放在/var/www/cgi-bin/目录下面，因此启动worker和命令如下(比如我们要开16个worker)： sudo nohup perl /var/www/cgi-bin/worker_bastion3.pl >~/worker_bastion3_log_1.txt & sudo nohup perl /var/www/cgi-bin/worker_bastion3.pl >~/worker_bastion3_log_2.txt & sudo nohup perl /var/www/cgi-bin/worker_bastion3.pl >~/worker_bastion3_log_3.txt & sudo nohup perl /var/www/cgi-bin/worker_bastion3.pl >~/worker_bastion3_log_4.txt & ... sudo nohup perl /var/www/cgi-bin/worker_bastion3.pl >~/worker_bastion3_log_16.txt & 而client会在提交任务的时候，由Java调用，因此不需要我们手动启动。 现在不再需要手动重启了。 运行sudo crontab -e（e代表edit），可以编辑创建一个cron任务，可能需要先选择编辑器，熟悉哪个选哪个就行了，我选的3. vim： @reboot cd /var/www/cgi-bin && sudo perl /var/www/cgi-bin/worker_Bastion3.pl > /var/log/worker_Bastion3_log_1.txt 2>&1 @reboot cd /var/www/cgi-bin && sudo perl /var/www/cgi-bin/worker_Bastion3.pl > /var/log/worker_Bastion3_log_2.txt 2>&1 @reboot cd /var/www/cgi-bin && sudo perl /var/www/cgi-bin/worker_Bastion3.pl > /var/log/worker_Bastion3_log_3.txt 2>&1 @reboot cd /var/www/cgi-bin && sudo perl /var/www/cgi-bin/worker_Bastion3.pl > /var/log/worker_Bastion3_log_4.txt 2>&1 ... @reboot cd /var/www/cgi-bin && sudo perl /var/www/cgi-bin/worker_Bastion3.pl > /var/log/worker_Bastion3_log_16.txt 2>&1 这样之后服务器重启，就不必再手动开这些进程了。 使用sudo crontab -l(l代表list)可以查看所有你创建的cron任务。注意：用sudo创建的任务用sudo查看，才能看得到，同样sudo crontab -l查看不到crontab -e 创建的任务。 相对于手动执行脚本，这里的配置有三个变化： 把log日志重定向到了/var/log/目录下，可以直接在这里查看错误信息。 不再需要用nohup命令了，nohup是因为我们用ssh登录，需要在ssh退出后脚本依然运行才这么做的，现在重启时系统系统这个脚本，这个脚本会一直留在系统中，不必再用nohup。 由cron启动脚本时，当前工作目录可能跟想象中不一样，我们执行sudo perl /var/www/cgi-bin/worker_bastion3.pl（不管用不用nohup）时，脚本的工作目录在/var/www/cgi-bin，而由cron执行时，当前工作目录却是sudo perl /var/www/cgi-bin/worker_bastion3.pl，导致脚本中使用相对目录的地方会报错，比如这里： $seqs > io("sequence/$jobName.fasta"); … 当然，好的习惯是尽量不要用相对路径，因为你不知道这个脚本会在哪里或者哪种环境下执行，执行时的当前工作目录也可能无法预测。 3. Python相关安装 Python在此系列项目当中，主要是用来提取特征，因此需要依次安装以下几个工具包： sudo apt-get install python-scipy sudo apt-get install python-dev sudo apt-get install python-numpy sudo apt-get install python-matplotlib sudo apt-get install python-pandas sudo apt-get install python-sklearn 4. R语言及相关包安装 R语言在此系列项目当中，既要提取部分特征，又要负责训练模型，还要使用ggplot2画图，所以有很多相关的包是要安装的。 首先安装R语言： sudo apt-get install r-base 然后安装以下几个包 (其实这个服务器在机器学习部分主要作用就是预测，因为训练部分的工作都会在线下进行，不过仍然将所有机器学习部分必须的包都记录在此，以备查阅)。 sudo权限启动R语言： sudo R 这里必须用sudo启动R安装，这样R包一般会安装在/usr/local/lib/R/site-library中，不用sudo权限，会把R包装在当前用户的个人空间，比如~/R/x86_64-pc-linux-gnu-library/3.2。在普通状态下这两个位置并无不同，但是如果当前用户进入root模式(比如用sudo -i命令)，再使用R就不能正确找到R包了。很不幸，因为我们用了crontab设置了worker开机自启动，导致在sudo模式调用了worker的程序，并由worker进一步调用了R程序，就没能找到普通权限下安装的R包，导致报错了。 然后在启动的R语言对话框中输入以下命令： install.packages("protr") install.packages("caret") install.packages("e1071") install.packages("plyr") install.packages("RSNNS") install.packages("ROCR") install.packages("ggplot2") install.packages("randomForest") 至此一个完整的机器学习项目的服务器就已经算是搭建好了。 需要格外注意的是，因为我们的缓存文件都在外接硬盘上，所以每次都重启服务器之后都需要手动加载此硬盘： sudo mount /dev/vdb /bastion3_cache/ 现在不用这么做了，通过配置/etc/fstab可以直接再重启服务器时自动挂载，在/etc/fstab文件中添加下面的行（需要用sudo编辑）： /dev/vdb /bastion3_cache auto defaults,nofail,x-systemd.requires=cloud-init.service,comment=cloudconfig 0 2 其中，/dev/vdb是要挂在的物理硬盘盘符，/bastion3_cache是挂载盘目录。 如果你不清楚哪个盘需要挂载，用df -h查看： ubuntu@bastion3:~$ df -h Filesystem Size Used Avail Use% Mounted on udev 32G 0 32G 0% /dev tmpfs 6.3G 180M 6.2G 3% /run /dev/vda1 9.9G 4.2G 5.2G 45% / tmpfs 32G 0 32G 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock tmpfs 32G 0 32G 0% /sys/fs/cgroup /dev/vdb 473G 9.0G 440G 3% /bastion3_cache tmpfs 6.3G 0 6.3G 0% /run/user/1000 如果有硬盘为未挂载，那Mounted on这列应该是空的，或者是/mnt（默认挂载在/mnt目录）。挂载前需要自己创建一个目录，比如sudo mkdir /bastion3_cache。
Overview1. 错误描述2. 解决方法 Overview 在做实验的时候因为要用到随机森林，所以使用了R中的randomForest包，但在画图的时候报了一个非常诡异的错误。 1. 错误描述 下面是我引入randomForest包之后的代码，这里省略了一些细节，只保留跟错误有关的代码: ## randomforest library("randomForest") # randomforest调参 bestmtryMatrix <- tuneRF(train.bal[,-1],train.bal[,1], ntreeTry=100, stepFactor=1.5,improve=0.01, trace=TRUE,plot=FALSE, dobest=FALSE) bestmtryMatrix # 找到最佳参数 bestmtry <- bestmtryMatrix[which.min(bestmtryMatrix[,2]),1] # 训练模型 rfNormal <-randomForest(Class~.,data=train.bal, mtry=bestmtry, ntree=1000, keep.forest=TRUE, importance=TRUE) # 预测 rfNormal.predictions <- predict(rfNormal,type="prob",newdata=test) 在画图时的代码： g <- ggplot(data=rocdata,aes(x=ejeX,y=ejeY))+geom_line(aes(colour=Metodo),size=0.8)+scale_colour_manual(values=c("red","blue","green4"))+xlab("False positive rate")+ ylab("True positive rate")+theme_custom()+theme(legend.position=c(0.73,0.1))+ #设定x，y轴坐标刻度 scale_x_continuous(limits=c(0, 1),breaks=seq(0,1,0.2))+ scale_y_continuous(limits=c(0, 1),breaks=seq(0,1,0.2)) # 添加一条对角线 g <- g+geom_abline(intercept=0,slope=1) 上面代码中，theme_custom()就是我自定义的样式函数，可以在 使用R语言ggplot2包画图时的一个不兼容问题 中查看这个函数的详细信息。 在运行时报了下面的错误： 错误于UseMethod("margin") : "margin"没有适用于"unit"目标对象的方法 Calls: theme_custom ... inherits -> theme -> element_text -> structure -> margin 停止执行 又是element_text中margin的问题，可见更新之后这里有点不稳定，我们在 使用R语言ggplot2包画图时的一个不兼容问题 讨论的问题也与margin相关。 2. 解决方法 刚开始我以为是这个函数名在randomForest中有同名函数导致冲突，所以修改了theme_custom()，改为theme_custom_chris()，结果依然报错。但是我试着删除了randomForest的相关代码（library("randomForest")这句也一定要删掉），则不再报错。 实际上，正是library("randomForest")引入randomForest包导致的问题，那在使用完randomForest之后，手动将它从当前的程序中去掉是不是就可以了呢？ 在R中使用完randomForest包的代码之后，ggplot画图代码之前，添加下面的代码： detach("package:randomForest", unload=TRUE) 意义也非常直观明了，在运行过程中detach randomForest包，然后重新运行程序，一切正常。
蛋白质序列处理程序之前得到的数据源太乱，这些天整理并重新摆放了一下，每一步的输入文件夹后缀都有一个-in，处理程序文件夹后缀为-run，输出文件夹后缀为-out，这样条理清晰了很多，今日记录，以方便日后查阅使用。 数据处理部分共分5步： 下载并分类(set class) 多步CD-hit 正负样本1:1平衡(Dataset balance) 特征计算(feature calculation) 特征选择(feature selection) 下面分别详细地记录每步的具体作用及用法。 1)下载并分类(set class) 通过DownldProtSeq.java从Effectorsequencesdata.txt中读取所需的蛋白质序列信息，从http://www.uniprot.org/uniprot/上面下载对应的蛋白质序列数据。 下载完成后保存在fastafiles文件夹中，与之前的BPBAacBi_pro文件夹和sieve文件夹中的.fasta文件一起，组成set class这一步骤的输入数据。 set class的作用是将蛋白质序列分类为positive和negative数据，positive数据加上1标记，negative数据加上-1标记。 set class这一步用到的是setcls_integ.sh文件调用fasta_setclass.py以及eft3_setclass.py两个Python脚本。 输出了T3fastaPool_clfed.fasta，T4posiNeg.fasta，T6posneg.fasta三个文件，并且这三个文件将会在第二步中作为输入文件。 2)多步CD-hit CD-hit这一步需要用到CD-hit软件包，详细信息见http://weizhongli-lab.org/cd-hit/。原本地文件中经过编译之后的cd-hit二进制文件在Linux上无法运行，故在删除了包内的.o文件以及所有的二进制文件后，在命令行中运行make openmp=yes将其重新编译，得到的cd-hit文件就可以使用了，使用方法如下: ./cd-hit -i <fasta-file> -o T6pn06snd.out -c 0.6 -n 4 这样会得到很多.out文件，这些文件将是第三步的输入文件。 3)正负样本1:1平衡(Dataset balance) 该步骤处理程序只有一个undersmple_neg.py脚本文件，目的是控制正负样本(positive和negative样本)的比例为1:1。平衡后的样本有三个：T3undrsmp.txt，T4undrsmp.txt，T6undrsmp.txt。 4)特征计算(feature calculation) 第四步比较复杂，又可分为7小步。前6小步中，计算出6个特征向量文件(file of feature vectors)，第7步将这些特征向量聚合在一起，形成一系列的.CSV文件，然后将这些.CSV文件按照T3，T4，T6分别放置。详见蛋白质序列特征向量计算—数据处理第(4)步。 5)特征选择(feature selection) 特征选择这一步，分别用了两种算法。这两种算法互不干涉，无先后顺序。 mRMR算法，详见http://penglab.janelia.org/proj/mRMR/。 用法如下： python fts_select.py <T3_cdhit_N30_50fts.txt> <csv-before-selection> <csv-after-selection> <50/100/200> 其中，<csv-before-selection>是第四步中得到的.CSV文件，<csv-after-selection>是本步得到的结果文件，<50/100/200>表示截取前<50/100/200>个特征，<T3_cdhit_N30_50fts.txt>是经过mrmr文件处理过后得到的一系列文件，全部在文件夹中。 InfoGain算法，用法如下： python weka_fts_slct.py <InfoGainFslct> <50/100/200> <csv-before-selection> <csv-after-selection> 其中<csv-before-selection>是第四步中得到的.CSV文件，<csv-after-selection>是本步得到的结果文件，<50/100/200>表示截取前<50/100/200>个特征，<InfoGainFslct>这一系列文件在文件夹中。
蛋白质序列特征向量计算—数据处理第(4)步
该步骤为数据处理的第(4)步，共包含6小步。 其中前三步： 1. AAC,Amino acid composition(AminoAcidC.py) 2. SEQ,Sequence(Seq.py) 3. eft3,amino acids combination properties(involving kmp algorithm)(Eft3.py) 这前三步用到feature_calc.sh和AminoAcidC.py, Seq.py, Eft3.py, kmp.py, eft3_fts.py共六个脚本文件， feature_calc.sh是前三步的程序入口，会自动调用五个py脚本。 这前三步，需要在针对T3undrsmp.txt,T4undrsmp.txt,T6undrsmp.txt运行脚本文件时，分别将参数N_term_rsds=25,30,50带入，这样会得到27个和T3aac_N25.txt类似格式的文件。将其分门别类放入9个文件夹，以供后三步使用。 后三步： 4. AAINDEX(support code/chenzheng) ./encode -i <chen’s file format> -o ../t3_1.aaindex -t aaindex 5. CKSAAP(support code/chenzheng) ./encode -i <chen’s file format> -o ../t3_1.cksaap -t cksaap (Chen’s aaindex cksaap output have a comma at end of each line) 6. PSSM python t34pssm.py T4undrsmp.txt ./t4 ./t4pssm 第4步和第5步中所需的<chen’s file format>,是T3undrsmp.txt,T4undrsmp.txt,T6undrsmp.txt三个文件经过fasta_chenfmt_std.py脚本文件处理之后得出的T3toChen.txt,T4toChen.txt,T6toChen.txt，这三个文件存放在文件夹Chen'sFormatFile中。 第4步和第5步中所需的encode文件需要将原文件夹中的二进制文件和.o文件删除，然后重新编译运行。具体编译方法，详见encode文件夹中的说明性文件Makefile。 这三步得出来的三个文件，分别对应T3,T4,T6放入前三步的九个文件夹中。这样，每个文件夹中均含有6个文件。 然后，Each of the step output a file of feature vectors AND assemble the CSV file，每6个特征向量文件聚合成一个CSV文件，这个文件包含了六种特征。这一步得出的9个CSV特征文件,在结果文件夹中。
Overview Weka is easy to use when we do feature selection and classification. Using Weka's friendly graphic user interface, we can try and validate multiple feature selection methods and classifiers that have already been implemented into Weka. This article tries to give a quick start guide about this wonderful tool. 1. Download Weka 1.1 About different versions You can download Weka with different versions from Weka's Download page. There are Stable book 3rd ed. version(3.6.12) and Developer version(3.7.12+) available. Stable book 3rd ed. version is a stable version for use. If this version can meet all your demands or you don't know what functions you need, use this one. Compared to the former versions of Weka, Developer version(3.7.12+) adopts a new architecture, which provides a package manager in the tool menu. Unlike that Stable book 3rd ed. version(3.6.12) provides all the methods and classifier it can, Developer version(3.7.12+) only provides a series of basic methods and classifiers in default, however, with a new-developed package manager. If you want some classifier, open the package manager and download this classifier, then you can use it in Weka. Taking feature selection as an instance, we want to use mRMR method to select features. Fortunately, mRMR is involved in weka at version 3.5.15. We don't need to update a new version since we only need this function. Open the package manager in the existing 3.7.12 version, we can easily download and use it. 1.2 For users in different platforms Weka provides a series of versions that can run on Windows, Mac and other platforms(a zip file). For Windows and Mac users, you can directly download the corresponding version, install it and use it. However, I recommend you to download a zip version to use. When you wanna use SVM classifier in Weka 3.6.12, you will need the zip version. (How to involve libSVM in weka 3.6.12 will be depicted in another article) 2. Use Weka If you download the non-zip version, I guess you are already using Weka. So we just talk about how to use the zip version. 2.1 Run Weka Enter the weka folder, and use the following command to start it: java -Xmx1000M -jar weka.jar Notice the parameter -Xmx1000M. This means Weka can use a maximum of 1000M memory to use. When you wanna training big data set, set a bigger value will prevent the breakdown of Weka(I use 4000M memory). 2.1 Run Weka anywhere We have already run Weka. There is still a problem: Every time we wanna use Weka, we have to enter the Weka folder and run the start command. By setting the environmental viable, we can tackle this problem. The setting in my computer is as follows: CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib:/Users/wangjiawei/weka/weka-3-6-12/weka.jar /Users/wangjiawei/weka/weka-3-6/ is the folder of Weka. After adding the folder address into CLASHPATH, we can use the start command at any place.
Overview 因为最近需要用到一些机器学习算法，Python的scikit-learn提供很多机器学习算法实现，可以很方便地用来做实验。今天在自己的电脑上安装了scikit-learn，并在此记录了安装的步骤。 安装pip 由于scikit-learn官方给的步骤是使用pip安装，所以要先安装pip。我是用了pip官方提供的安装页面 但是没有成功。因此想使用homebrew安装pip。使用以下命令安装： sudo brew install pip 提示如下： Homebrew provides pip via: `brew install python`. However you will thenhave two Pythons installed on your Mac, so alternatively you can:sudo easy_install pip 因为我之前已经装过了Python的easy_install，因此可以直接使用easy_install安装，命令如下： sudo easy_install pip 这样就顺利地装好了pip。 安装scikit-learn 需要安装以下包：numpy scipy scikit-learn，其中前两个是scikit-learn的依赖库，选择性安装nose,一个Python下面的测试库，可以用来测试scikit-learn。命令如下： sudo pip install -U numpy scipy scikit-learn 安装成功，并显示安装的地点： numpy in /Library/Python/2.7/site-packages scipy in /Library/Python/2.7/site-packages scikit-learn in /Library/Python/2.7/site-packages 这时候运行程序，导入sklearn，很可能出现 No module named sklearn 这个错误主要是由于Python程序找不到安装好的scikit-learn，原因是可能你的电脑里装了好几个Python，但是scikit-learn没有装到你现在用的那一个里面。 设置正确的Python 首先使用如下命令查看： port select --list python 在我的电脑上结果如下： Available versions for python: none python25-apple python26-apple python27 (active) python27-apple 现在起作用的是python27，但是要注意的是，scikit-learn安装在/Library/Python/2.7/site-packages，这个目录并不是python27的目录，而是python27-apple的目录。 解决方案：可以将scikit-learn复制到python27目录相应的位置，或者将默认的Python编译器改为python27-apple。 命令如下： sudo port select --set python python27-apple 结果如下： Selecting 'python27-apple' for 'python' succeeded. 'python27-apple' is now active. 测试scikit-learn 好啦，总算成功，使用nose测一下吧。 python -c "import nose; nose.main()" -v sklearn 或者直接在Python外使用 nosetests -v sklearn 也是可以的。 测试成功，就可以开始使用scikit-learn啦！