您正在查看: 2016年4月

python解析命令行参数

Overview

python程序也可以拥有C语言风格的命令行参数,例如-h/--help输出帮助信息,-i/--input提示输入文件,-o/--output提示输出文件等等。除了清晰明了,还有一个好处就是输入参数的顺序可以随意一些。
python中,实现这个功能的函数跟C/C++中一样,也是getopt().下面用实际的代码展示一下。

1. getoptions.py

首先,我们定义一个usage()函数,用以展示帮助信息:

def usage():
    print "getoptions.py usage:"
    print "python getoptions.py <options> <source files> "
    print "-i,--input: the input filename."
    print "-o,--ouput: the output filename."
    print "-h,--help: show the help information."

主函数部分如下:

#引入sys和getopt包
import sys, getopt
opts, args = getopt.getopt(sys.argv[1:],'i:o:h',['input=','output=','help'])
inputFile=""
outputFile=""
for opt, arg in opts:
    if opt in ('-i','--input'):
        inputFile = arg
    elif opt in ('-o','--output'):
        outputFile = arg
    elif opt in ('-h', '--help'):
        usage()
        sys.exit(2)
    else:
        usage()
        sys.exit(2)
'''
业务逻辑代码
'''

主函数代码中,我们可以看到

(1). getopt这个函数是在getopt这个包中的。

这个函数接收2或者3个参数:第一个参数是命令行中所有的输入;第二个参数是所有的短option;第三个是可选项,长option。这个可选的标志就是方括号[].

(2). 注意到,i/o后面均有:,而h后面没有:

这表明,需要输入的option必须加:,而且,在长option后面还要加上赋值号=
不需要输入的option,不可以加:=

(3). 在解析option的时候,短的option前加-,长的option前加--

更多详细内容,请参考官方文档getopt — C-style parser for command line options

python处理数据常用工具包

Overview

在数据挖掘(机器学习)领域,python之所以被广泛应用,与其强大的工具包关系密切。正好最近的项目里频繁地使用python处理数据,于是记录一下pythonscipy numpy scikits-learn等几个常用工具包的安装及其常用函数的使用。这里只记录在ubuntu 14.04下的安装使用,Mac系统的参考Chris的另一篇文章:Mac上安装Python机器学习库scikit-learnWindows版本的就不做介绍了。

1.安装工具包

相比于mac,在linux系统上安装这几个工具包十分快捷方便,分别只需一条命令即可成功。

  • 安装python-scipy
    sudo apt-get install python-scipy
    
  • 安装python-numpy
    sudo apt-get install python-numpy
    
  • 安装python-sklearn
    sudo apt-get install python-sklearn
    
  • 安装python_dev
    sudo apt-get install python-dev
    
  • 安装python-matplotlib
    sudo apt-get install python-matplotlib
    
  • 安装python-pandas
    sudo apt-get install python-pandas
    

其中需要注意的是,最好先安装python-scipypython-numpypython_dev这三个包,因为其他包的安装依赖这几个包。

2.工具包简单使用

我们以对训练集归一化的代码为例,简单认识一下这几个常用包中的常用函数。

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#Copyright Chris & Young

def usage():
    print "normalize_train.py usage:"
    print "python normalize_train.py <options> <source files> "
    print "-i,--input: input a training dataset feature file."
    print "-o,--ouput: output a normalized training dataset feature file."
    print "-H,--header: input 'T' if the input_file contains header row, else input 'F'."
    print "-c,--class: input 'T' if the input_file contains class label column, else input 'F'."
    print "-h,--help: show the help information."

import re
import pandas as pd
import numpy as np
import fileinput
import sys, getopt
from os import listdir
from os.path import isfile, join
from sklearn import preprocessing

opts, args = getopt.getopt(sys.argv[1:], 'i:o:H:c:h',['input=','output=','header=','class=','help'])
input_file=""
output_file=""
header_input=""
class_input=""
#col_start这个变量,是归一化开始列的index。根据是否有class列而变化。
col_start=0
for opt, arg in opts:
    if opt in ('-i','--input'):
        input_file = arg
        elif opt in ('-o','--output'):
            output_file = arg
        elif opt in('-H','--header'):
            header_input = arg
            if header_input == "T":
                header_input='infer'
            elif header_input == "F":
                header_input=None
    elif opt in ('-c','--class'):
        class_input = arg
        if class_input=="T":
            col_start+=1
    elif opt in ('-h', '--help'):
        usage()
            sys.exit(2)
        else:
            usage()
            sys.exit(2)
#读取数据到dataframe中
df = pd.read_csv(input_file,header=header_input)
#print df
#df_columns存储读取进来的数据的header,即列头。
df_columns=df.columns
#再进行一次判断,如果没有header,列头为None,矩阵转换回数据框的时候需要用到列头。
if header_input==None:
    df_columns=None
#print df_columns
#将数据框分成两部分:class列单独拿出来,其余部分归一化处理
dataframe1 = df.ix[:,range(col_start)]
dataframe2 = df.ix[:,col_start:]
#print dataframe1,dataframe2
#matrix1存储第一个数据框的矩阵形式
matrix1 = np.array(dataframe1)
#print matrix1
#第二个数据框需要转化为float类型
dataframe2 = np.float64(dataframe2)
#下面两行代码是核心归一化代码
data_scaled = preprocessing.MinMaxScaler().fit(dataframe2)
matrix2 = data_scaled.transform(dataframe2)
#将两个矩阵水平连起来
matrix_final=np.hstack((matrix1,matrix2))
#print matrix_final
#矩阵加上列头重新变为数据框
df_final=pd.DataFrame(matrix_final,columns=df_columns)
#print df_final
if header_input==None:
    head=False
else:
    head=df_columns
#将数据框存储为csv格式的文件    
df_final.to_csv(output_file,header=head,index=False)

可以看到,常用的函数有如下几个:

(1). numpy.array:把数据框变成矩阵

 matrix1 = np.array(dataframe1)   

(2). numpy.float64:把数据变成float64类型

 dataframe2 = np.float64(dataframe2) 

(3). numpy.hstack:把两个行数相同的矩阵水平连接起来

 matrix_final=np.hstack((matrix1,matrix2))

把列数相同的矩阵垂直拼接是另一个函数:numpy.vstack

(4). pandas.DataFrame:把矩阵变成数据框

 df_final=pd.DataFrame(matrix_final,columns=df_columns)

(5). preprocessing.MinMaxScaler().fittransform

 data_scaled = preprocessing.MinMaxScaler().fit(dataframe2)
 matrix2 = data_scaled.transform(dataframe2)

preprocessing.MinMaxScaler().fit这个函数先得到数据的每一列的极值,然后存储起来供下一步transform进行归一化。

这几个函数只是在我们数据处理过程中经常用到的,其他更丰富的函数请参考官方文档。

KNN与K-means的区别

Overview

在机器学习(数据挖掘)领域,有两种算法,经常让初学者混淆,那就是:KNN分类和K-means聚类。而实际上这两种算法没有任何关系,只是名字里面都有一个K。下面,我们记录一下这两种算法,并分析一下它们的区别。

1.KNN分类

实际上KNN算法也可以用来做回归,但是我们这里只讨论分类。KNN全名是k-Nearest Neighbors,用法如下:
(1).将已经分好类的样本的特征输入,这些样本就是“参考样本”,也就是下一步的输入的未知样本的“邻居”;
(2).输入待分类样本,对于每个新样本,我们通过这个样本的周围最近的K个已经分好类的邻居的类别来判断它的类别。如果在这K个邻居中,某个类的数量最多,那么我们判断该样本为此类。
原则上二分类时,这个参数K取奇数为佳。一般情况下这个K取值不宜太小,以消除噪声影响,但是过大又会使分类边界模糊,所以这个K需要进行参数优化。原理图来自维基百科:

220px-KnnClassification.svg.png

(3).这个被分好类的新样本,不作为下一个需要分类的样本的参照样本。且分类只次一次,不需要像K-means聚类那样迭代多次。
(4).一般情况下,我们在计算距离时,使用欧氏距离即可。

2.K-means聚类

K-means聚类是无监督的聚类算法。我们不知道这些样本的具体分类,也不知道具体有多少类。所以只能根据经验告诉程序或者软件,我们假设有K个分类。用法如下:

(1).我们假设样本有3类,即K=3.我们选择3个距离适当的坐标点作为这个3类的中心点(不一定必须是真实的点)。事实上,第一次选择的坐标点,将会很大程度上影响运算速度。如下图,我们选择红绿蓝3个坐标点为初始类中心点。

124px-K_Means_Example_Step_1.svg.png

(2).将所有的待分样本按照最近邻原则分类。这是第一次迭代。

139px-K_Means_Example_Step_2.svg.png

(3).这样,第一次分类结束。我们再根据最新的分类,计算出每个类中样本的平均坐标值,取为该类的新中心点。

139px-K_Means_Example_Step_3.svg.png

(4).按照该方法,进行多次迭代,直到三个类的中心点收敛。这样,我们就得到这些样本的具体分类了。

139px-K_Means_Example_Step_4.svg.png

3.两者之间的差异

两种算法之间有多种差异,如下:

  • KNN为分类,K-means为聚类;
  • KNN为监督学习,K-means为无监督学习;
  • KNN的输入样本为带label的,K-means的输入样本不带label
  • KNN没有训练过程,K-means有训练过程;
  • K的含义不同

两种算法之间有一点相似:
都是计算最近邻,一般都用欧氏距离。

这篇文章主要参考了以下几篇文章:
K-nearest neighbors algorithm
k-means clustering
Kmeans、Kmeans++和KNN算法比较

文章中所有图片均来自维基百科。