Python 3 学习笔记

来源:互联网 发布:centos nginx安装配置 编辑:程序博客网 时间:2024/05/21 14:54

  最近在学习《机器学习实战(Machine Learning in Action)》,因为个人比较喜欢Python 3,而这本书里面的代码都是通过Python 2实现的,所以自己在调试的时候会改写成Python 3。
  在前几章里问题都不是很大,但是在ch09 树回归这一章中出现了很多小问题,现在此做一个笔记,如果有错误望指正。

问题一

  在使用书上ch09中的代码时,运行遇到的第一个问题就是类型错误,无法映射。错误提示为:TypeError: unsupported operand type(s) for /: 'map' and 'int'

def loadDataSet(fileName):    dataMat = []    fr = open(fileName)    for line in fr.readlines():        curLine = line.strip().split('\t')        fltLine = map(float, curLine)        dataMat.append(fltLine)    return dataMat

  在loadDataSet这个方法中,使用了一个map方法来对从文本文件中读取的数据进行映射处理,也就是把读取到的string转换为float。这一个简单的类型转换按照书上实现的方法在Python 2中不会报错。
  但是在Python 3中,map方法返回的是一个map对象,因此对于这个错误,解决办法很简单。

def loadDataSet(fileName):    dataMat = []    fr = open(fileName, 'r')    for line in fr.readlines():        curLine = line.strip().split('\t')        fltLine = list(map(float, curLine))  # 方法1        # fltLine = [float(item) for item in curLine] # 方法2        dataMat.append(fltLine)    fr.close()    return dataMat

  这里给出两种解决办法:
  方法1,将map方法返回的map对象再转换为list对象就行了。
  方法2,使用列表推导式做一个处理。
  这里给出的两种解决办法的运行结果完全一样,具体使用看个人喜好吧,关于性能问题暂不作考虑。

问题二

  解决了问题一之后,重新运行,又出现新的错误,说matrix类型不能被哈希。错误提示为:TypeError: unhashable type: 'matrix'
  在chooseBestSplit方法里有这么一条语句:

for splitVal in set((dataSet[:, featIndex])):

  这里报错就是无法把matrix对象转换为set类型,这里找了一个解决办法是将这一句改为:

for splitVal in set((dataSet[:, featIndex].T.A.tolist())[0]):

  解释一下就是对于矩阵中满足featIndex的一列,先将其转置(.T),然后转换为numpy array类型(.A),再转换为list类型(.tolist())。
  在一系列转换之后,就可以达到最初想要的效果了。

问题三

  解决了问题二之后,再运行,出现新的错误。错误提示为:IndexError: index 0 is out of bounds for axis 0 with size 0
  在书中binSplitDataSet方法的三个参数为数据集、待切分的特征、特征值。该方法用于在给定特征和特征值的情况下,通过数组过滤的方式将数据集进行切分并返回两个子集。书中给出的实现为:

def binSplitDataSet(dataSet, feature, value):    mat0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:][0]    mat1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:][0]    return mat0,mat1

  其实可以在测试的时候就发现,并不像书上给出的运行结果一样,mat0的值是一个一行的向量,mat1的值是一个三行的矩阵。
  解决办法很简单,讲两条语句最后的[0]删去就行了。

def binSplitDataSet(dataSet, feature, value):    mat0 = dataSet[nonzero(dataSet[:, feature] > value)[0], :]    mat1 = dataSet[nonzero(dataSet[:, feature] <= value)[0], :]    return mat0, mat1

  解释一下,该方法使用的是数组过滤的办法,对于特征feature,先过滤出特征feature的值大于(或小于等于)value的。这里使用nonzero()方法返回的是一个元素均为boolean类型的list,而这个list[0]的值就是对应过滤出的元素下标,换句话说就是过滤出的值在原数组中的位置。最后一步是一个Python切片操作,通过dataSet[index, :]把对应的向量提取出来。
  个人理解在这里需要得到的是被切分的两个子集,所以最后的[0]下标运算是多余的。

小结

  在ch09中,9.3.2之前的问题就是这些。解决了这三个问题之后,程序可以正常执行,得出和书上一样的测试结果。
  运行截图如下:
  运行结果