ValueError: Expected 2D array, got 1D array instead

时间:2021-09-26 09:50:02

python有一个非常棒的机器学习依赖包sklearn,用于实现机器学习的很多算法,本文将介绍用sklearn中的决策树的接口来实现决策树。

决策树是一种用于分类的算法,是一种监督学习算法,具体有id3、c4.5和cart三种算法组成。首先通过csv来导入数据集,注意csv格式是按照每一列以逗号为分隔符的形式。但是因为调用sklearn的包时,需要将数据集的表现格式进行转化,也就是通过也就是比如某一个特征取值为youth、middle_aged和senior,那么会通过转化方式将这三个特征变为如果取youth,那么该值取1,否则取0;如果取middle_aged,那么该值就取1,否则就取0,依次类推。这里sklearn就有一个DictVectorizer类转化工具,用于将一个数据集表示成只包含数值型数据的一个list,这样就可以应用相应的算法进行计算了。

然后就是调用sklearn中的决策树算法来实现,默认tree下关于决策树有两个可以调用的文件,即DecisionTreeClassifier 和 DecisionTreeRegressor两个包,一个用于分类,另一个用于回归。可以用训练集对其进行训练模型,然后用新的测试集对该模型进行测试,看看效果。具体的代码实现如下:

# -*- coding=utf-8 -*-

import math
from sklearn.feature_extraction import DictVectorizer
import csv
from sklearn import tree
from sklearn import preprocessing
from sklearn.externals.six import StringIO

allElectronicsData = open(r'/AllElectronics.csv','rb') #这里的r保持字符串原始,不对其中的符号进行转义
reader = csv.reader(allElectronicsData)
headers = reader.next()    #输出CSV文件的第一行TITLE
print headers

featureList = []
labelList = []

for row in reader:
    labelList.append(row[len(row) - 1])
    rowDict = {}
    for i in range(1,len(row) - 1):    #选取每一行的特征值,从1开始是因为第0个表示的是行号,非特征
        rowDict[headers[i]] = row[i]   #取每一行最后一列的分类值
    featureList.append(rowDict)

print featureList

vec = DictVectorizer()  #将一个数据集表示成一种只包含有数值型数据的一个list,然后就可以用于机器学习的计算
dummyX = vec.fit_transform(featureList).toarray()     #change to a matrix

print str(dummyX)
print vec.get_feature_names()


lb = preprocessing.LabelBinarizer()       #这个是将最后一列分类别进行转化的类
dummyY = lb.fit_transform(labelList)      #将类别按照0,1等数字来进行转化
print str(dummyY)

clf = tree.DecisionTreeClassifier(criterion='entropy')   #采用熵的方式来作决策树的决策
clf = clf.fit(dummyX,dummyY)
print str(clf)
with open("/AllElectronics.dot","w") as f:
    f = tree.export_graphviz(clf,feature_names=vec.get_feature_names(),out_file=f)

oneRowX = dummyX[0,:]
print "oneRow: " + str(oneRowX)

newRowX = oneRowX

newRowX[0] = 1
newRowX[2] = 0
print "newRowX: " + str(newRowX)

predictedY = clf.predict(newRowX.reshape(1,-1))
print "predictedY: " + str(predictedY)

注意,在生成dot格式后,其实是很难看出这棵树的具体形态,这时候就需要通过转化,将dot格式转化成pdf格式,就能清晰地看到整棵树的形态。这里就需要用到一个工具,graphviz,这是一个开源的画图包,集成了很多相关的画图工具包,在mac下可以通过brew install graphviz来安装。安装完后,在命令行黑窗口应用dot -T pdf inputfile.dot -o output.pdf命令来实现转化。当然了通过graphviz还可以转化好多种不同格式的数据,比如有png等。

 

注意上述predict预测函数的参数中,一开始是导入newRowX,但是发现报错,出现的错误为

ValueError: Expected 2D array, got 1D array instead

这个错误的原因是需要指定相关的行列数,那么就改成 newRowX.reshape(1,-1)来实现。