自用,断断续续看了一个月,没有特别整理,自己后续查看的笔记
专家系统
参考数据库:
知识表示
特征为列
监督学习:知道要预测什么,即目标变量的分类信息
回归与分类
无监督学习:没有类别信息;也不给定目标值
聚类
寻找描述统计值的过程称为 密度估计
用于减少数据特征的维度
根据出现的次数使用k - 近邻算法来分类
简单来说,k - 近邻算法采用测量不同特征值之间的距离 方法来进行分类
精度高、对异常值不敏感、无数据输入假定
计算复杂度高、空间复杂度高
适用数据范围:数据型和标称型
工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似的数据(最相邻)的分类标签。一般来说我们只选择本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
例子:P16 图2-1
评估分类器:计算错误率
def file2matrix(filename): #将文本转为numpy
fr = open(filename)
numberOfLines = len(fr.readlines()) #得到文件行数
returnMat = zeros((numberOfLines,3)) #创建以0填充的numpy矩阵
classLabelVector = [] #prepare labels return
fr = open(filename)
index = 0
for line in fr.readlines():
line = line.strip()
#截取回车符
listFromLine = line.split('\t')
#将上步数据分割成整行的列表
returnMat[index,:] = listFromLine[0:3]
#取前三个元素储存到特征矩阵中
classLabelVector.append(int(listFromLine[-1])) #listFromLine默认字符串
#‘-1’:负索引的方法,将数据定位到最后一列元素
#将列表中最后一列存储到向量classLabelVector中
index += 1
return returnMat,classLabelVector
import kNN
import matplotlib.pyplot as plt
import numpy as np
datingDataMat,datingLabels = kNN.file2matrix('datingTestSet2.txt')
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,0], datingDataMat[:, 1],
#绘制矩阵第一第二列属性
15.0*np.array(datingLabels), 15.0*np.array(datingLabels))
#利用变量datingLabels存储的类标签属性,在散点图上绘制了色彩不等、尺寸不同的点
plt.show()
newValue = (oldValue-min)/(max-min)
#min与max分别为数据集中最大特征值与最小特征值
def autoNorm(dataSet):
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = zeros(shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - tile(minVals, (m,1))
normDataSet = normDataSet/tile(ranges, (m,1)) #element wise divide
return normDataSet, ranges, minVals
def datingClassTest():
hoRatio = 0.50 #hold out 10% 这里取50%
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #load data setfrom file
normMat, ranges, minVals = autoNorm(datingDataMat)
#读入数据并归一化
m = normMat.shape[0]
#返回行数
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
print ("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i]))
if (classifierResult != datingLabels[i]): errorCount += 1.0
print ("the total error rate is: %f" % (errorCount/float(numTestVecs)))
#print (errorCount)
def classifyPerson():
resultList = ['not at all', 'in small doses', 'in large doses']
percentTats = float(input("percentage of time spent playing video games?"))
ffMiles = float(input("frequent flier miles earned per year?"))
inceCream = float(input("liters of ice cream consumed per year?"))
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
norMat, range, minVals = autoNorm(datingDataMat)
inArr = array([ffMiles, percentTats, inceCream])
classifierResult = classify0((inArr - minVals)/range, norMat, datingLabels, 3)
print("You will probably like this person: ",resultList[classifierResult - 1])
from numpy import *
import operator
#运算符模块
from os import listdir
def classify0(inX, dataSet, labels, k): #构建分类器
# inX(向量)用于分类;dataSet为输入的训练样本集;
# 标签向量为labels其元素数目与矩阵dataSet的行数相同;
# k表示用于选择最近的邻居的数目
dataSetSize = dataSet.shape[0]
#获取dataSet的行数
diffMat = tile(inX, (dataSetSize,1)) - dataSet
#在行上重复inX向量dataSetSize次
#获取dataSet与构建的矩阵的差值diffMat
sqDiffMat = diffMat**2
#取平方
sqDistances = sqDiffMat.sum(axis=1)
#行向量相加
distances = sqDistances**0.5
#开根号完成欧式距离公式
#1.以上为距离计算
sortedDistIndicies = distances.argsort()
#将数据从小到大排列
classCount={}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
#按照距离的从小到大选取各个数据点的标签向量
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
#将字典分解为元组列表
#2.以上至1.为选择距离最小的k个点
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
#按照元组第二个元素的次序对元组进行排序(逆序)
return sortedClassCount[0][0]
#返回发生频率最高的元素的标签
def file2matrix(filename): #将文本转为numpy
fr = open(filename)
numberOfLines = len(fr.readlines()) #得到文件行数
returnMat = zeros((numberOfLines,3)) #创建以0填充的numpy矩阵
classLabelVector = [] #prepare labels return
fr = open(filename)
index = 0
for line in fr.readlines():
line = line.strip()
#截取所有的回车符
listFromLine = line.split('\t')
#将上步数据分割成整行的列表
returnMat[index,:] = listFromLine[0:3]
#取前三个元素储存到特征矩阵中
classLabelVector.append(int(listFromLine[-1])) #listFromLine默认字符串
#‘-1’:负索引的方法,将数据定位到最后一列元素
#将列表中最后一列存储到向量classLabelVector中
index += 1
return returnMat,classLabelVector
def autoNorm(dataSet):
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = zeros(shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - tile(minVals, (m,1))
normDataSet = normDataSet/tile(ranges, (m,1)) #element wise divide
return normDataSet, ranges, minVals
def datingClassTest():
hoRatio = 0.50 #hold out 10%
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #load data setfrom file
normMat, ranges, minVals = autoNorm(datingDataMat)
#读入数据并归一化
m = normMat.shape[0]
#返回行数
numTestVecs = int(m*hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
print ("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i]))
if (classifierResult != datingLabels[i]): errorCount += 1.0
print ("the total error rate is: %f" % (errorCount/float(numTestVecs)))
#print (errorCount)
def classifyPerson():
resultList = ['not at all', 'in small doses', 'in large doses']
percentTats = float(input("percentage of time spent playing video games?"))
ffMiles = float(input("frequent flier miles earned per year?"))
inceCream = float(input("liters of ice cream consumed per year?"))
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
norMat, range, minVals = autoNorm(datingDataMat)
inArr = array([ffMiles, percentTats, inceCream])
classifierResult = classify0((inArr - minVals)/range, norMat, datingLabels, 3)
print("You will probably like this person: ",resultList[classifierResult - 1])
i = True
while i:
classifyPerson()
print("")
judgement = input("Play again? [Y/N]")
if judgement == 'N':
i = False
import matplotlib.pyplot as plt
import numpy as np
import operator
# 运算符模块
from os import listdir
def classify0(inX, dataSet, labels, k): # 构建分类器
# inX(向量)用于分类;dataSet为输入的训练样本集;
# 标签向量为labels其元素数目与矩阵dataSet的行数相同;
# k表示用于选择最近的邻居的数目
dataSetSize = dataSet.shape[0]
# 获取dataSet的行数
diffMat = tile(inX, (dataSetSize, 1)) - dataSet
# 在行上重复inX向量dataSetSize次
# 获取dataSet与构建的矩阵的差值diffMat
sqDiffMat = diffMat ** 2
# 取平方
sqDistances = sqDiffMat.sum(axis=1)
# 行向量相加
distances = sqDistances ** 0.5
# 开根号完成欧式距离公式
# 1.以上为距离计算
sortedDistIndicies = distances.argsort()
# 将数据从小到大排列
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
# 按照距离的从小到大选取各个数据点的标签向量
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
# 将字典分解为元组列表
# 2.以上至1.为选择距离最小的k个点
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
# 按照元组第二个元素的次序对元组进行排序(逆序)
return sortedClassCount[0][0]
# 返回发生频率最高的元素的标签
def file2matrix(filename): # 将文本转为numpy
fr = open(filename)
numberOfLines = len(fr.readlines()) # 得到文件行数
returnMat = np.zeros((numberOfLines, 3)) # 创建以0填充的numpy矩阵
classLabelVector = [] # prepare labels return
fr = open(filename)
index = 0
for line in fr.readlines():
line = line.strip()
# 截取所有的回车符
listFromLine = line.split('\t')
# 将上步数据分割成整行的列表
returnMat[index, :] = listFromLine[0:3]
# 取前三个元素储存到特征矩阵中
classLabelVector.append(int(listFromLine[-1])) # listFromLine默认字符串
# ‘-1’:负索引的方法,将数据定位到最后一列元素
# 将列表中最后一列存储到向量classLabelVector中
index += 1
return returnMat, classLabelVector
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,0], datingDataMat[:, 1],
#绘制矩阵第一第二列属性
15.0*np.array(datingLabels), 15.0*np.array(datingLabels))
#利用变量datingLabels存储的类标签属性,在散点图上绘制了色彩不等、尺寸不同的点
plt.show()
朴素贝叶斯算法
决策树与k近邻算法都是给出明确的答案,不过分类器有时会产生错误的结果,这是可以要求分类器给出一个最优类别的猜测结果,同时给出这个猜测的概率估计值
优点:在数据较少的情况下仍然有效,可以处理多类别问题
缺点:对于输入数据的准备方式较为敏感
适用数据类型:标称型数据
贝叶斯:
例子给的网站无法访问:参考此博文http://www.knowsky.com/885215.html
RSS源推荐(中文RSS):https://www.douban.com/note/609155195/
RSS源推荐(英文RSS):https://www.jianshu.com/p/433b1282ebe8
留存交叉验证
for i in range(10):
randIndex = int(random.uniform(0,len(trainingSet)))
testSet.append(trainingSet[randIndex])
del(trainingSet[randIndex])
#删除测试集;使得余下的作为训练集,实现留存交叉验证
#即,五十个样本;十个验证;其余四十个训练
#随机构建训练集
支持向量机
推荐b站白板手推SVM(清晰):https://www.bilibili.com/video/av28186618/
序列最小化(Sequential Minimal Optimization, SMO)算法(支持向量机的一种方法):一种求解支持向量机二次规划的算法
优点:泛化错误低,计算开销不大,结果易解释
缺点:对参数调节和核函数的选择敏感,原始分类器不加修改仅适用与二类问题
数据适用类型:数值型和标称型数据
支持向量(support vector)就是离分隔超平面最近的那些点
分类器的工作原理:
其中||w||表示w的二范数,求所有元素的平方和,然后再开方。
理解支持向量机:强烈推荐观看此文章:https://www.sohu.com/a/128747589_614807
SVM:1.间隔 2.对偶 3.核技巧
SVM分为三个算法:
hard-margin SVM:最初用来解决二分类问题
f(w) = sign(w^Tx + b) 判别模型 ——超平面
为了找到一条线(二维上是超平面)(让它离样本点的距离都足够大(鲁棒性强))
max margin(最大间隔分类器)
理解松弛因子:https://blog.csdn.net/chaipp0607/article/details/75949812
径向基核函数:
margin的定义:margin(w,b) = min distance(w,b,xi)
m i n d i s t a n c e = 1 / ∣ ∣ w ∣ ∣ ∣ w T x + b ∣ min distance = 1/||w|||w^Tx+b| mindistance=1/∣∣w∣∣∣wTx+b∣
点到直线距离公式
大于1的优化问题:引入拉格朗日乘子法
Quadratic programming (QP) 二次规划
SMO算法
既能做分类;又能做回归
决策树是最经常用的数据挖掘算法
k-近邻算法的最大缺点在于无法给出数据的内部含义;决策树的主要优势在于数据形式非常容易理解
计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不想关特征数据
可能会产生过度匹配问题
数据需要离散型数据,必须标称化
一般采用二分法划分数据(例子采用ID3算法划分数据集)
ID3(信息增益)的思想是:递归调用划分数据集实现branch的再划分
递归结束的条件是:程序遍历完所有划分数据集的属性,或者每个分支下的所有实例都具有相同的分类。
C4.5:信息增益率
CART:Gini系数
评价函数:类似于损失函数
信息增益(取结点是计算的前后熵值的变化就称为信息增益):
信息增益值最大的作为根节点
划分数据的大原则是:将无序的数据变得更加有序
使用信息论在划分数据前或后度量化信息的内容,这个变化称为信息增益
集合信息的度量方式称为香农熵或者简称为熵,这个名字来源于信息论之父克劳德·香农
熵定义为信息的期望值
如果待分类的事务可能划分在多个分类中,则符号xi的信息可定义为:
l(xi) = -log_2p(xi)
其中p(xi)是选择该分类的概率
计算所有类别所有可能值包含的信息期望值
H = -∑(^n_i=1)p(xi)log_2p(xi)
其中n为分类的数目
熵越高,则混合的数据越多
构造树的基本想法是随着树的深度的增加,节点的熵迅速的降低 。熵降低得越快越好,这样我们有希望得到一棵高度最矮的决策树
熵值可以用作衡量结点的标准
另一个度量集合无序程度的方法是基尼不纯度(Gini impurity),简单的说就是从一个数据集中随机选取子项,度量其被错误分类到其他分组里的概率。
e.g:
[[1, 1, ‘yes’], [1, 1, ‘yes’], [1, 0, ‘no’], [0, 1, ‘no’], [0, 1, ‘no’]]
这个是我们的数据集。
如果我们选取第一个特征值也就是需不需要浮到水面上才能生存来划分我们的数据,这里生物有两种可能,1就是需要,0就是不需要。那么第一个特征的取值就是两种。
如果我们按照第一个特征的第一个可能的取值来划分数据也就是当所有的样本的第一列取1的时候满足的样本,那就是如下三个:
[1, 1, ‘yes’], [1, 1, ‘yes’], [1, 0, ‘no’]
可以理解为这个特征为一条分界线,我们选取完这个特征之后这个特征就要从我们数据集中剔除,因为要把他理解为分界线。那么划分好的数据就是:
[[1, ‘yes’], [1, ‘yes’], [0, ‘no’]]
如果我们以第一个特征的第二个取值来划分数据集,也就是当所有样本的第二列取1的时候满足的样本,那么就是
[[1, 1, ‘yes’], [1, 1, ‘yes’], [0, 1, ‘no’], [0, 1, ‘no’]]
那么得到的数据子集就是下面这个样子:[[1,’yes’],[1,’yes’],[1, ‘no’], [1, ‘no’]]
此段参考:https://blog.csdn.net/chichoxian/article/details/51952065
'''
Created on Oct 12, 2010
Decision Tree Source Code for Machine Learning in Action Ch. 3
@author: Peter Harrington
'''
from math import log
import operator
import treePlotter
def createDataSet():
dataSet = [[1, 1, 'yes'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
labels = ['no surfacing','flippers']
#change to discrete values
return dataSet, labels
def calcShannonEnt(dataSet):
#计算给定数据的香农熵
numEntries = len(dataSet)
labelCounts = {}
#存储最后一列的数值
for featVec in dataSet: #the the number of unique elements and their occurance
currentLabel = featVec[-1]
if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0
#键值不存在;扩展字典并将当前键值加入字典
labelCounts[currentLabel] += 1
#键值记录了当前类别出现的次数
shannonEnt = 0.0
for key in labelCounts:
prob = float(labelCounts[key])/numEntries
shannonEnt -= prob * log(prob,2) #log base 2
return shannonEnt
def splitDataSet(dataSet, axis, value):
retDataSet = []
for featVec in dataSet:
#遍历数据集中的每个元素,一旦发现符合要求的值,则将其添加到新创建的列表里
if featVec[axis] == value:
reducedFeatVec = featVec[:axis] #chop out axis used for splitting
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
#当我们按照某个特征划分数据集时,就需要将所有符合要求的元素抽取出来
return retDataSet
def chooseBestFeatureToSplit(dataSet):
#该函数实现了选取特征,划分数据集,计算得出最好的划分数据集的特征
numFeatures = len(dataSet[0]) - 1 #the last column is used for the labels
baseEntropy = calcShannonEnt(dataSet)
bestInfoGain = 0.0; bestFeature = -1
for i in range(numFeatures): #iterate over all the features
featList = [example[i] for example in dataSet]#create a list of all the examples of this feature
uniqueVals = set(featList) #get a set of unique values
#去重/集合数据类型与列表类型相似;不同之处在于集合类型中每个值互不相同
newEntropy = 0.0
for value in uniqueVals:
subDataSet = splitDataSet(dataSet, i, value)
prob = len(subDataSet)/float(len(dataSet))
newEntropy += prob * calcShannonEnt(subDataSet)
#得到的所有唯一特征值的熵求和
infoGain = baseEntropy - newEntropy #calculate the info gain; ie reduction in entropy
if (infoGain > bestInfoGain): #compare this to the best gain so far
bestInfoGain = infoGain #if better than current best, set to best
bestFeature = i
return bestFeature #returns an integer
#返回最好的特征划分的索引值
def majorityCnt(classList):
classCount={}
for vote in classList:
if vote not in classCount.keys(): classCount[vote] = 0
classCount[vote] += 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
#返回了出现次数最多的分类名称
def createTree(dataSet,labels,featLabels):
classList = [example[-1] for example in dataSet]
if classList.count(classList[0]) == len(classList):
return classList[0]#stop splitting when all of the classes are equal
# 递归函数的第一个停止条件: 类别完全相同
if len(dataSet[0]) == 1: #stop splitting when there are no more features in dataSet
return majorityCnt(classList)
# 递归函数的第二个停止条件:使用完了所有的特征,仍不能将数据集划分成仅包含唯一类别的标签
bestFeat = chooseBestFeatureToSplit(dataSet)
#选取最好的特征
bestFeatLabel = labels[bestFeat]
featLabels.append(bestFeatLabel)
myTree = {bestFeatLabel:{}}
del(labels[bestFeat])
#清空变量为下一次递归做准备
featValues = [example[bestFeat] for example in dataSet]
uniqueVals = set(featValues)
for value in uniqueVals:
subLabels = labels[:] #copy all of labels, so trees don't mess up existing labels
myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels,featLabels)
return myTree
# def classify(inputTree,featLabels,testVec):
# firstStr = list(inputTree.keys())[0]
# secondDict = inputTree[firstStr]
# firstStr = next(iter(inputTree))
# featIndex = featLabels.index(firstStr)
# key = testVec[featIndex]
# valueOfFeat = secondDict[key]
# if isinstance(valueOfFeat, dict):
# classLabel = classify(valueOfFeat, featLabels, testVec)
# else: classLabel = valueOfFeat
# return classLabel
def classify(inputTree, featLabels, testVec):
firstStr = next(iter(inputTree)) #获取决策树结点
secondDict = inputTree[firstStr] #下一个字典
featIndex = featLabels.index(firstStr)
for key in secondDict.keys():
if testVec[featIndex] == key:
if type(secondDict[key]).__name__ == 'dict':
classLabel = classify(secondDict[key], featLabels, testVec)
else: classLabel = secondDict[key]
return classLabel
def storeTree(inputTree,filename):
import pickle
fw = open(filename,'wb')
pickle.dump(inputTree,fw)
fw.close()
def grabTree(filename):
import pickle
fr = open(filename,'rb')
return pickle.load(fr)
if __name__ == '__main__':
fr = open('lenses.txt')
lenses = [inst.strip().split('\t') for inst in fr.readlines()]
lensesLabels = ['age', 'prescript', 'astigmatic', 'tearRate']
featLabels = []
lensesTree = createTree(lenses, lensesLabels,featLabels)
# treePlotter.createPlot(lensesTree)
i = True
while i:
print("Please input the message what you want to test")
x = input("")
testVec = x.split(" ")
#testVec = ['normal', 'yes', 'hyper', 'pre']
result = classify(lensesTree, featLabels, testVec)
print(result)
print("")
print("Play again? [Y/N]")
judgement = input("")
if judgement == 'N':
i = False
treePlotter完整代码
'''
Created on Oct 14, 2010
@author: Peter Harrington
'''
import matplotlib.pyplot as plt
decisionNode = dict(boxstyle="sawtooth", fc="0.8")
leafNode = dict(boxstyle="round4", fc="0.8")
arrow_args = dict(arrowstyle="<-")
#定义描述树节点的格式
def getNumLeafs(myTree):
numLeafs = 0
firstStr = list(myTree.keys())[0]
secondDict = myTree[firstStr]
for key in secondDict.keys():
if type(secondDict[key]).__name__=='dict':
#type函数能判断子节点是否为字典类型
numLeafs += getNumLeafs(secondDict[key])
else: numLeafs +=1
return numLeafs
def getTreeDepth(myTree):
maxDepth = 0
firstStr = list(myTree.keys())[0]
secondDict = myTree[firstStr]
for key in secondDict.keys():
if type(secondDict[key]).__name__=='dict':
thisDepth = 1 + getTreeDepth(secondDict[key])
else: thisDepth = 1
if thisDepth > maxDepth: maxDepth = thisDepth
return maxDepth
#以上两个函数说明了如何在python字典类型中存储树的信息
def plotNode(nodeTxt, centerPt, parentPt, nodeType):
createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction',
#直接再函数名后边加上(.xx,即为函数创建了全局变量.xx)
#| 'axes fraction' | 0,0 是轴域左下角,1,1 是右上角 |指定的是xy的坐标
xytext=centerPt, textcoords='axes fraction',
#| 'axes fraction' | 0,0 是轴域左下角,1,1 是右上角 |指定的是xytext的坐标
va="center", ha="center", bbox=nodeType, arrowprops=arrow_args )
# 点注释的位置;与注释框的样式;箭头的样式
def plotMidText(cntrPt, parentPt, txtString):
xMid = (parentPt[0]-cntrPt[0])/2.0 + cntrPt[0]
yMid = (parentPt[1]-cntrPt[1])/2.0 + cntrPt[1]
createPlot.ax1.text(xMid, yMid, txtString, va="center", ha="center", rotation=30)
#在父子节点间填充文本信息
def plotTree(myTree, parentPt, nodeTxt):#if the first key tells you what feat was split on
#plotTree.yOff plotTree.xOff追踪已绘节点位置,以及指向下个节点位置
numLeafs = getNumLeafs(myTree) #this determines the x width of this tree
depth = getTreeDepth(myTree)
firstStr = list(myTree.keys())[0] #the text label for this node should be this
cntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2.0/plotTree.totalW, plotTree.yOff)
plotMidText(cntrPt, parentPt, nodeTxt)
#计算父节点与子节点的中间位置
plotNode(firstStr, cntrPt, parentPt, decisionNode)
secondDict = myTree[firstStr]
plotTree.yOff = plotTree.yOff - 1.0/plotTree.totalD
for key in secondDict.keys():
if type(secondDict[key]).__name__=='dict':#test to see if the nodes are dictonaires, if not they are leaf nodes
plotTree(secondDict[key],cntrPt,str(key)) #recursion
else: #it's a leaf node print the leaf node
plotTree.xOff = plotTree.xOff + 1.0/plotTree.totalW
plotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode)
plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))
plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalD
#if you do get a dictonary you know it's a tree, and the first element will be another dict
def createPlot(inTree):
fig = plt.figure(1, facecolor='white')
fig.clf()
#新建图形清空绘图区
axprops = dict(xticks=[], yticks=[])
createPlot.ax1 = plt.subplot(111, frameon=False, **axprops) #no ticks
#createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropses
plotTree.totalW = float(getNumLeafs(inTree))
plotTree.totalD = float(getTreeDepth(inTree))
plotTree.xOff = -0.5/plotTree.totalW; plotTree.yOff = 1.0;
plotTree(inTree, (0.5,1.0), '')
plt.show()
# def createPlot():
# fig = plt.figure(1, facecolor='white')
# fig.clf()
# createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropses
# plotNode('a decision node', (0.5, 0.1), (0.1, 0.5), decisionNode)
# plotNode('a leaf node', (0.8, 0.1), (0.3, 0.8), leafNode)
# plt.show()
def retrieveTree(i):
listOfTrees =[{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}},
{'no surfacing': {0: 'no', 1: {'flippers': {0: {'head': {0: 'no', 1: 'yes'}}, 1: 'no'}}}}
]
return listOfTrees[i]
#createPlot(thisTree)
线性回归
Logistic回归 :
w : = w + α ▽ w f ( w ) w:=w+α▽_wf(w) w:=w+α▽wf(w)
w : = w − α ▽ w f ( w ) w:=w-α▽_wf(w) w:=w−α▽wf(w)
Sigmoid函数:
随机梯度上升算法:一种在线学习算法(一次仅使用一个样本点来更新回归系数;由于可以在新样本到来之前对分类器进行增量式更新,因此称为在线学习);相对应的普通的梯度上升算法为一次性处理所有数据被称作是**“批处理”**
处理数据中的缺失值:
本章小结
Logistic回归的目的是寻找一个非线性函数Sigmoid的最佳拟合参数,求解过程可以由最优化算法完成。在最优化算法中,最常用的就是梯度上升算法,而梯度上升算法又可以简化为随机梯度上升算法
局部加权线性回归
Ridge回归
Lasso最小回归系数估计
元算法的思路:类比于:当做出重要决定时,大家可能会考虑吸取多个专家的意见而不只是个人的意见
可能会利用修改后的指标来评价分类器的性能
分类算法各有优缺点,我们可以将不同的分类器组合起来,这种组合结果则称为集成方法或者元算法
优点:
缺点:
适用的数据类型:数值型和标称型数据
bagging(自举汇聚算法):基于数据随机重新抽样的分类器算法
boosting(AdaBoost):一种类似于bagging的技术
bagging中不同的分类器是通过串行训练而获得的
boosting是通过集中关注被已有分类器错分的那些数据来获得新的分类器
其中bagging中分类器权重是相等的,而boosting中的分类器权重并不相等,其中每个权重代表的是其对应分类器在上一轮迭代中的成功度
运行过程:
训练数据中的每个样本,并赋予其一个权重,这些权重构成了向量D。一开始,这些权重都初始化为相等值。首先在训练数据上训练出一个弱分类器并计算该分类器的错误率(未正确分类的样本数目 / 所有样本数目),然后在同一数据集上再次训练弱分类器。在分类器的第二次训练当中,将会重新调整样本的权重,其中第一次分对的样本的权重将会降低,而第一次分错的样本的权重将会提高。为了从所有弱分类器中得到最终的分类结果,AdaBoost为每个分类器都分配了一个权重值alpha(α=1/2ln((1-错误率)/错误率)),这些alpha值是基于每个弱分类器的错误率进行计算的。
可以把弱分类器想象成SVM中的一个核函数
优点:结果易于理解,计算上不复杂
缺点:对非线性的数据拟合不好
简单来说,岭回归就是在矩阵XTX上加上一个λI从而使得矩阵非奇异,进而能对XTX + λI求逆。其中矩阵I是一个mxm的单位矩阵,对角线上元素全为1(岭的由来),其他元素为0.
岭回归用来处理特征数多与样本数的情况
优点:易于实现
缺点:可能收敛到局部最小值,在大规模数据集上收敛较慢。
计算质心-分配-重新计算 反复迭代以上过程,直到所有数据点的簇分配结果不再改变为止
优点:降低数据的复杂性,识别最重要的多个特征
缺点:不一定需要,且可能损失有用信息
优点:简化数据,去除噪声,提高算法的结果
缺点:数据的转换可能难以理解
适用数据类型:数值型数据
SVD_用于图像压缩
矩阵进行SVD处理 => 可以将数据压缩到若干概念中
SVD => 高维映射到低维(矩阵)
SVD是矩阵分解的一种类型
例如:SVD会得到两个矩阵:U和VT:其中,VT会反映到用户上,U会反应到数据集上
例如:SVD将数据集矩阵Data分解成三个矩阵。其中,若Data为m x n矩阵,那么U为m x m矩阵(U为A的左奇异向量);Σ为mxn(Σ为A的奇异值);V^T为n x n(V^T为A的右奇异向量);其中,Σ只有对角元素(其值为奇异值)(从大到小排列),其余元素为零。
Data * Data^T特征值的平方根 = Σ的特征值 => 其对映Data的奇异值;
其中Data的奇异值与Σ的奇异值称为数据的主要特征
基于物品相似度还是基于用户相似度?
如果用户数目很多,倾向于使用基于物品相似度的计算方法
tile([0,0],(2,1))#在列方向上重复[0,0]1次,行2次
'''
output >>>
array([[0, 0],
[0, 0]])
'''
tile([0,0],(1,3))#在列方向上重复[0,0]3次,行1次
'''
output >>>
array([[0, 0, 0, 0, 0, 0]])
'''
我们平时用的sum应该是默认的axis=0 就是普通的相加,而当加入axis=1以后就是将一个矩阵的每一行向量相加
c = np.array([[0, 2, 1], [3, 5, 6], [0, 1, 1]])
print c.sum()
print c.sum(axis=0)
print c.sum(axis=1)
#结果分别是:19, [3 8 8], [ 3 14 2]
#axis=0, 表示列。
#axis=1, 表示行。
get()方法语法:
dict.get(key, default=None)
参数:
返回值:返回指定键的值,如果值不在字典中返回默认值None。
#!/usr/bin/python
dict = {'Name': 'Zara', 'Age': 27}
print "Value : %s" % dict.get('Age')
print "Value : %s" % dict.get('Sex', "Never")
'''
output >>>
Value : 27
Value : Never
'''
字典的items方法作用:是可以将字典中的所有项,以列表方式返回。因为字典是无序的,所以用items方法返回字典的所有项,也是没有顺序的。
字典的iteritems方法作用:与items方法相比作用大致相同,只是它的返回值不是列表,而是一个迭代器。
iteritems()方法在需要迭代结果的时候使用最适合,而且它的工作效率非常的高。
sorted() 函数对所有可迭代的对象进行排序操作。
sort 与 sorted 区别:
sorted 语法:
sorted(iterable[, cmp[, key[, reverse]]])
参数说明:
key 和 reverse 比一个等价的 cmp 函数处理速度要快。这是因为对于每个列表元素,cmp 都会被调用多次,而 key 和 reverse 只被调用一次
Python的元组与列表类似,不同之处在于元组的元素不能修改。
元组使用小括号,列表使用方括号。
元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可。
使用参考:http://www.runoob.com/python/python-tuples.html
a = [1,2,3]
b = [4,5,6]
a.append(b)
print(a)
print("")
a.extend(b)
print(a)
'''
output >>>
[1, 2, 3, [4, 5, 6]]
[1, 2, 3, [4, 5, 6], 4, 5, 6]
'''
描述:Python 字典(Dictionary) keys() 函数以列表返回一个字典所有的键。
语法:
dict.keys()
实例:
#!/usr/bin/python
dict = {'Name': 'Zara', 'Age': 7}
print "Value : %s" % dict.keys()
#output >>>
Value : ['Age', 'Name']
eg:
#生成一个0-9的列表
si=[x for x in range(10)]
X[:,0]
# 二维数组取第1维所有数据
X[:,1]
# 第2列
X[0,:]
# 第1行
X[3,:]
# 第三行
X[1:4,:]
# 第一二三行
在python2中
firstStr = myTree.keys()[0]
在python3中
firstStr = list(myTree.keys())[0]
def storeTree(inputTree,filename):
import pickle
fw = open(filename,'w')
pickle.dump(inputTree,fw)
fw.close()
def grabTree(filename):
import pickle
fr = open(filename)
return pickle.load(fr)
改为:
def storeTree(inputTree,filename):
import pickle
fw = open(filename,'wb')
pickle.dump(inputTree,fw)
fw.close()
def grabTree(filename):
import pickle
fr = open(filename,'rb')
return pickle.load(fr)
Python3.5中:iteritems变为items
myset = 'With Jose out of town, \
do you want to meet once in a while to keep things going and \
do some interesting stuff?'
print(myset.split())
'''
output >>>
['With', 'Jose', 'out', 'of', 'town,', 'do', 'you', 'want', 'to', 'meet', 'once', 'in', 'a', 'while', 'to', 'keep', 'things', 'going', 'and', 'do', 'some', 'interesting', 'stuff?']
'''
import re
myset = 'With Jose out of town, \
do you want to meet once in a while to keep things going and \
do some interesting stuff?'
regEx = re.compile('\\W*')
print(regEx.split(myset))
tok for tok in regEx.split(myset) if len(tok) > 0
#删除空格
tok.lower() for tok in regEx.split(myset) if len(tok) > 0
#大写转小写
>>> range(1,5)
[1,2,3,4]
>>> np.arange(1,5)
array([1,2,3,4])
>>>
>>> range(1,10,2)
[1,3,5,7,9]
>>> np.arange(1,10,2)
array([1,3,5,7,9])
>>>
mat.getA()
将自身矩阵变量转化为ndarray类型的变量。
等价于np.asarray(self)
array和asarray都可以将结构数据转化为ndarray,但是主要区别就是当数据源是ndarray时,array仍然会copy出一个副本,占用新的内存,但asarray不会。