赞
踩
python魔法用法:a, b = b, a + b
迭代器 生成器 Iterable
# coding:utf-8 # 生成器(iterator;代表无限大数据流 迭代器是生成器,调用next计算下一个,直到异常) # 迭代器(generator):yield 和(i for i in range(10),调用next计算下一个,直到异常) # iterable 可迭代对象 list str 可以用for循环的都是 生成器和迭代器都是iterable但不是iterator # 获得iterable iterator对象iter() # list存储容量有限但是iteriator存储容量无限 from collections import Iterable,Iterator,Generator def o(): print(1) yield 1 print(2) yield 2 print(2) yield 3 b=(i for i in range(0,10)) print(type(o()),type(b)) print('next b',next(b)) o=o() # for x in o: # print('x',x) if(isinstance(o,Generator)): while (True): try: print('o',next(o)) except StopIteration as e: print(e.value) break print('---------------') for n in b: print(n) print('---------------') print(isinstance(o,Iterable)) print(isinstance(o,Iterator)) print(isinstance(o,Generator)) print(isinstance(b,Iterable)) print(isinstance(b,Iterator)) print(isinstance(b,Generator)) l=[2,3] print('l',next(iter(l)))
python函数
# coding:utf-8 def test0(a,b=1,*m ): print(a,b,m) def test(a,b=1,* ,d,**kw): print(a,b,d) for i in kw: print(i,kw.get(i)) # 位置参数和命名关键字参数(*后边的参数,符号和位置参数一样没有*,只是前边多了个'*,')必须有,默认参数a= # 可变参数和关键字参数(**kw:传入值可以时a='2',也可以是**{'a':'2'})可以没有,如果已经组装的数组参数传入可变参数前边加*,*[1,2,3] # ,可变参数后边的命名关键子参数可以不用加*;必选参数、默认参数、可变参数、命名关键字参数和关键字参数 def test1(a,*s,d,**kw): print(a,s,d) for i in kw: print(i,kw.get(i)) if __name__=='__main__': test0(1) print('-------') test(1,d=9) print('-------') test(1,d=9,s='4',m='8') print('-------') test1(1,6,d='4',m='8') print('-------') test1(1,*[6,9],d='4',m='8') print('-------') test1(1, *[6, 9],d='9',**{'l':'4', 'm':'8'})
使用枚举类
# coding:utf-8 from enum import Enum,unique Month=Enum('Month',('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) for name,member in Month.__members__.items(): print(name,member,member.value,'--') @unique class WeekDay(Enum): Sun=0 Mon = 1 Tue = 2 Wed = 3 Thu = 4 Fri = 5 Sat = 6 print(WeekDay.Mon,WeekDay.Mon.value) class Gender(Enum): Male = 0 Female = 1 class Student(object): def __init__(self, name, gender): self.name = name self.gender = gender s=Student('menghui',Gender.Male) # 结果 ------------------------------ Jan Month.Jan 1 -- Feb Month.Feb 2 -- Mar Month.Mar 3 -- Apr Month.Apr 4 -- May Month.May 5 -- Jun Month.Jun 6 -- Jul Month.Jul 7 -- Aug Month.Aug 8 -- Sep Month.Sep 9 -- Oct Month.Oct 10 -- Nov Month.Nov 11 -- Dec Month.Dec 12 -- WeekDay.Mon 1
面向对象:类的属性
# coding :utf-8 class Student(object): __slots__ = ('_Student__name','age','sex','score','hobby') # 限制必须只有几种属性 country='China' #类属性,所有实例都可以访问 def __init__(self,value): # 初始化变量必须有的值 __name是私有变量 self.__name=value def get_name(self): return self.__name def set_sex(self, value): self.sex = value @property def sscore(self): return self._score @sscore.setter def sscore(self,value): self._score= value pass # 给类增加函数 def set_age(self,value): self.age=value s=Student('menghui') Student.set_age=set_age #s.name='menghui' s.hobby='basketball' # 外部变量可以随便更改hobby变量 class Screen(object): # __slots__ = ('width','height','resolutio') @property def width(self): return self._width @width.setter def width(self,value): self._width=value @property def height(self): return self._height @height.setter def height(self,value): self._height=value @property def resolution(self): return self.width*self.height pass if __name__=='__main__': s.set_age(5) s.set_sex('male') # 不用 s.score=89 print(s.country,Student.country,s.age,s.get_name(),s._Student__name,s.sex,s.score,s.hobby) print('---------') # 测试: s = Screen() s.width = 1024 s.height = 768 print('resolution =', s.resolution) if s.resolution == 786432: print('测试通过!') else: print('测试失败!')
获取对象信息 type() isinstanceof(a,int)
面向对象的继承和多态,支持多继承class(object,Animal,Fly)
# coding:utf-8 class Animal(object): def run(self): print('animal ran') pass class Cat(Animal): def run(self): print('cat ran') pass class Dog(Animal): def run(self): print('dog ran') pass def runTwice(animal): animal.run() animal.run() if __name__ == '__main__': dog = Dog() cat = Cat() animal = Animal() # 多态 runTwice(animal) print('---------') runTwice(cat) print('---------') runTwice(dog)
矩阵的切片
取出矩阵的第二行,第三列
Arr1=Arr[1:2,2:3]
对矩阵进行转置运算
ArrT=Arr.T
求矩阵的内积运算
Arr2=np.dot(Arr.T,Arr)
或者转化成mat直接相乘,mat就是矩阵,按矩阵的性质 Arr2=np.mat(Arr.T)*np.mat(Arr)
两个矩阵进行合并
A=np.array([[1,2,3],[2,3,4]])
B=np.array([[5,6,7]])
C=np.r_[A,B] #增补行
得到C
[1,2,3],
[2,3,4],
[5,6,7]
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
print 'vstack:\n',np.vstack((arr1, arr2)) #按行向量处理增补行
print 'c_:\n',np.c_[arr1,arr2] # 按列向量处理增补列
print 'hstack:\n', np.hstack((arr1, arr2)) # 按行向量处理增补列
print 'r_:\n',np.r_[arr1,arr2] # 按行向量处理增补列
a1 = np.array([[1, 2], [3, 4], [5, 6]])
a2 = np.array([[7, 8], [9, 10], [11, 12]])
print 'vstack:\n',np.vstack((a1, a2))
print 'c_:\n',np.c_[a1,a2]
print 'hstack:\n', np.hstack((a1, a2))
print 'r_:\n',np.r_[a1,a2]
得到结果
vstack: [[1 2 3] [4 5 6]] c_: [[1 4] [2 5] [3 6]] hstack: [1 2 3 4 5 6] r_: [1 2 3 4 5 6] vstack: [[ 1 2] [ 3 4] [ 5 6] [ 7 8] [ 9 10] [11 12]] c_: [[ 1 2 7 8] [ 3 4 9 10] [ 5 6 11 12]] hstack: [[ 1 2 7 8] [ 3 4 9 10] [ 5 6 11 12]] r_: [[ 1 2] [ 3 4] [ 5 6] [ 7 8] [ 9 10] [11 12]]
在指定位置插入矩阵
A=np.array([[1,2,3],[3,4,5],[4,7,9]])
S=np.insert(A,1,np.array([[2,2,2]]),0)
得到矩阵
[1, 2, 3],
[2, 2, 2],
[3, 4, 5],
[4, 7, 9]
花式索引 取出矩阵C的第三列和第一列组成新矩阵
S[np.ix_([0,1,2,3],[2,0])]
得到
[[3, 1],
[2, 2],
[5, 3],
[9, 4]])
m=S[[0,1],[2,0]]
得到一维数组:0行2列和1行0列的数组
array([3,2])
等效于下边
m=np.array([S[0,2],S[1,0]])
m=array([3, 2])
一维数组的引用m[0]
将一维数组变成二维数组m.reshape(1,3)
变成一行三列
试二维数组具有表的性质
类表操作
假设下边是三个学生的成绩
score=np.array([[50,60,60],[80,82,90],[70,66,78]],dtype=np.float64)
三个学生矩阵
name=np.array(['xiaoming','xiaohong','xiaogang'],dtype=np.str_)
三门科目分别是
item=np.array(['yuwen','yingyu','shuxue'],dtype=np.str_)
现在取出小红的成绩
score[name=='xiaohong']
score[name==’xiaohong’,item==’yuwen’]
np.a[:-(3+1):-1]
###python绘图
#引入对应的库函数
import matplotlib.pyplot as plt
from numpy import *
#绘图
fig = plt.figure()
ax = fig.add_subplot(349)
ax.plot(x,y)
plt.show()
#######其中,参数349的意思是:将画布分割成3行4列,图像画在从左到右从上到下的第9块,如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ETfr9tpl-1591425060264)(http://image.codeweblog.com/upload/3/d7/3d7ccf7235b66a08_thumb.jpg)]
######参见网址:http://www.cnblogs.com/shanlizi/p/6850318.html
#导入必要的模块 import numpy as np import matplotlib.pyplot as plt #产生测试数据 x = np.arange(1,10) y = x fig = plt.figure() ax1 = fig.add_subplot(111) #设置标题 ax1.set_title('Scatter Plot') #设置X轴标签 plt.xlabel('X') #设置Y轴标签 plt.ylabel('Y') #画散点图 ax1.scatter(x,y,c = 'r',marker = 'o') #设置图标 plt.legend('x1') #显示所画的图 plt.show()
#####如果要画出高阶函数Sigmoid
#导入必要的模块 import numpy as np import matplotlib.pyplot as plt import math #产生测试数据 x = np.arange(-10,10,0.01) y=[] for i in x: y.append(1/(math.exp(-i)+1)) fig = plt.figure() ax1 = fig.add_subplot(111) #设置标题 ax1.set_title('Scatter Plot') #设置X轴标签 plt.xlabel('X') #设置Y轴标签 plt.ylabel('Y') #画散点图 ax1.scatter(x,y,c = 'r',marker = 'o') #设置图标 plt.legend('x1') #显示所画的图 plt.show()
另一种画出该图形的方法
import numpy as np
import matplotlib.pyplot as plt
def Sigmoid(x):
return 1/(np.exp(-x)+1) #矩阵每一个数据都进行这样计算
x=np.arange(-10,10,0.01)
y=Sigmoid(x)
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(x,y,marker='o',color='red')
plt.show()
画出三维图形
import matplotlib.pyplot as plt # 绘图用的模块 from mpl_toolkits.mplot3d import Axes3D # 绘制3D坐标的函数 import numpy as np def fun(x, y): return np.power(x, 2) + np.power(y, 2) fig1 = plt.figure() # 创建一个绘图对象 ax = fig1.add_subplot(111, projection='3d') # 用这个绘图对象创建一个Axes对象(有3D坐标) X = np.arange(-2, 2, 0.1) Y = np.arange(-2, 2, 0.1) # 创建了从-2到2,步长为0.1的arange对象 # 至此X,Y分别表示了取样点的横纵坐标的可能取值 # 用这两个arange对象中的可能取值一一映射去扩充为所有可能的取样点 X, Y = np.meshgrid(X, Y) Z = -X-Y-1 # 用取样点横纵坐标去求取样点Z坐标 plt.title("This is main title") # 总标题 ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=plt.cm.coolwarm) # 用取样点(x,y,z)去构建曲面 ax.set_xlabel('x label', color='r') ax.set_ylabel('y label', color='g') ax.set_zlabel('z label', color='b') # 给三个坐标轴注明 plt.show() # 显示模块中的所有绘图对象
降低维度的算法PCA:找出最大差异性、次大差异性,方差由大到小。
决策树可以构造简单的分类器,SVM可以构造更为精确的分类器,但是不容易解释。
线性方称组与矩阵:
https://blog.csdn.net/guoziqing506/article/details/80557920
协方差与矩阵的关系: https://blog.csdn.net/capecape/article/details/79162167 https://blog.csdn.net/h2026966427/article/details/79252011 https://blog.csdn.net/qq_29750461/article/details/81625470
特征值特征向量的几何含义: https://blog.csdn.net/fuming2021118535/article/details/51339881
矩阵乘法对应了一个变换,是把任意一个向量变成另一个方向或长度都大多不同的新向量。在这个变换的过程中,原向量主要发生旋转、伸缩的变化。如果矩阵对某一个向量或某些向量只发生伸缩变换,不对这些向量产生旋转的效果,那么这些向量就称为这个矩阵的特征向量,伸缩的比例就是特征值。
定义的特征值和特征向量有什么实际用途呢?在这里我举个数据挖掘算法中重要的一个算法:PCA(主成分分析),如下图:
如果我们单独看某一个维度的话,比如看x1这个维度:
可以看到将点投影到x1这个维度上看的话,图1的数据离散性最高,图3较低,图2数据离散性是最低的。数据离散性越大,代表数据在所投影的维度上具有越高的区分度,这个区分度就是信息量。如果我们用方差来形容数据的离散性的话,就是数据方差越大,表示数据的区分度越高,也就是蕴含的信息量是越大的。
基于这个知识,如果我们想对数据进行降维的话,比如图1的两个维度的数据降成一维,我们可以选择保留X1这个维度的数据,因为在这个维度上蕴含的信息量更多。
同理,图2就可以保留x2这个维度的数据。但是,问题来了,图3应该保留哪个维度的数据呢?答案是保留哪个维度都不好,都会丢失较大的信息量。但是,如果我们把图3的坐标轴旋转一下
比较容易看出,图3在新的坐标轴下就能进行降维了。所以选取正确的坐标轴,然后根据各个维度上的数据方差大小
,决定保留哪些维度的数据,这样的做法就是主成分分析的核心思想。
选取正确的坐标轴的过程中,我们需要一个矩阵变换,就类似于这样:
也就是:
其实,经过数学上的推导的,我们就可以知道,特征值对应的特征向量就是理想中想取得正确的坐标轴,而特征值就等于数据在旋转之后的坐标上对应维度上的方差。
也就是说,直接求出矩阵A的特征向量得出对应的特征向量。我们就能找到旋转后正确的坐标轴。这个就是特征值和特征向量的一个实际应用:得出使数据在各个维度区分度达到最大的坐标轴。
所以,在数据挖掘中,就会直接用协方差矩阵的特征值来描述对应特征向量方向上包含的信息量,而某一特征值除以所有特征值的和的值就为:该特征向量的方差贡献率(方差贡献率代表了该维度下蕴含的信息量的比例。)
通常经过特征向量变换下的数据被称为变量的主成分,当前m个主成分累计的方差贡献率达到一个较高的百分数(如85%以上)的话,就保留着这m个主成分的数据。实现了对数据进行降维的目的。整个主成分分析的算法原理也就是这个。
####### KNN算法又叫K-最近邻算法是最简单的一种分类算法,输入是数值型输出是标量型数据,优点是算法简单,缺点是算法效率低,无法解释算法结果,根据两点距离越近越相似的思想进行编写。
# -*- coding:UTF-8 -*- from numpy import * import operator from os import listdir # KNN算法 def classify0(inX, dataSet, labels, k): ''' :param inX: 输入某个样本数据,一行输入数据(1*n) :param dataSet:样本数据矩阵 :param labels:样本数据每条数据对应的标签 :param k: k近邻算法对应的数量,一般取常数值 :return:返回标签值最多的标签 ''' dataSetSize = dataSet.shape[0] #获取样本数据的行数 # 数组求差,相同行列数的数据对应位置求差: # tile是将一个数组扩展成一个 和样本数据同行数,只有一列的二维数组,详细见htlp(tile) diffMat = tile(inX, (dataSetSize,1)) - dataSet sqDiffMat = diffMat**2 #每个位置求平方 sqDistances = sqDiffMat.sum(axis=1) #对每一行将所有列加起来求和 distances = sqDistances**0.5 #对矩阵中每个数据开根号 sortedDistIndicies = distances.argsort() #argsort()函数是将x中的元素从小到大排列,提取其对应的index(索引),然后输出到y classCount={} for i in range(k): voteIlabel = labels[sortedDistIndicies[i]] #k个依次距离最近的标签值 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #如果标签在字典中就返回当前标签在字典中的值,否则返回0,其实就是计数功能 # classCount.iteritems()返回一个可以迭代的对象,将字典转化成可迭代 {'hh': 1, 'bb': 2}=》<dictionary-itemiterator object at 0x000000000AD45AE8> #可以理解为{'hh': 1, 'bb': 2}=》[(hh', 1),('bb',2)]用for循环可以print打印, key=operator.itemgetter(1)按第一个作用域排序即1 2,倒序 # 见https://blog.csdn.net/dongtingzhizi/article/details/12068205 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] #返回标签值最多的标签 # 使用KNN算法的例子 def createDataSet(): group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) #样本 labels = ['A','A','B','B'] #标签值 return group, labels group,labels=createDataSet(); print classify0([0.0],group,labels,3) def file2matrix(filename): ''' 读取文件,将文件转化为矩阵,比如txt类型的文件 :param filename: 带有文件路径的文件名 :return:返回矩阵 返回标签 ''' fr = open(filename) numberOfLines = len(fr.readlines()) #文件行数 returnMat = zeros((numberOfLines,3)) #准备‘返回矩阵’ classLabelVector = [] #准备‘返回标签’ fr = open(filename) index = 0 for line in fr.readlines(): line = line.strip() listFromLine = line.split('\t') returnMat[index,:] = listFromLine[0:3] #取出数组的前3个每赋值给‘返回矩阵’ classLabelVector.append(int(listFromLine[-1])) #数组的最后一列的值赋值给‘返回标签classLabelVector’ index += 1 return returnMat,classLabelVector def autoNorm(dataSet): ''' 数据归一化,为了消除不同维度的数据单位不一样带来的误差 :param dataSet: 输入矩阵 :return: normDataSet:归一化后的矩阵 ranges 矩阵范围 minVals 矩阵每列的最小值 ''' minVals = dataSet.min(0) # 获取每列的最小值 min(1)获取每行的最大值 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)) # 然后再乘以最大值减去最小值 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) #测试数据的数量numTestVecs errorCount = 0.0 # 选择前numTestVecs的数量作为测试样本,剩下的样本为训练样本。 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
适用范围:条件因素特征和结果因素特征是标称型数据。优点:可以清晰的看出数据划分的过程 ,缺点:无法直接处理数值型数据,容易出现过度匹配问题,需要剪枝
信息增益和熵的概念:待分类的事务可能划分在多个分类之中,Xi 是一个分类,则符号分类 Xi 的 信息定义为: -log2p(xi),其中p(xi)是选择该分类的概率。
熵定义为信息的期望值
H=-\Sigma^n_{i=1}p(x_i)log_2p(x_i)
关于熵和决策树的理解:http://www.cnblogs.com/muzixi/p/6566803.html
信息增益 = entroy(前) - entroy(后) 对于待划分的数据集D,其 entroy(前)是一定的,但是划分之后的熵 entroy(后)是不定的,entroy(后)越小说明使用此特征划分得到的子集的不确定性越小(也就是纯度越高),因此 entroy(前) - entroy(后)差异越大,信息增益越大,说明使用当前特征划分数据集D的话,其纯度上升的更快,越能快速的划分数据集。
决策树核心代码:
tree.py
''' Decision Tree Source Code for Machine Learning in Action Ch. 3 @author: ''' from math import log import operator # 简单的测试数据集产生 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): ''' 求一个矩阵的信息熵,熵越高,信息越复杂越无序,则混合的数据也越多,我们可以在数据集中添加更多的分类 :param dataSet:标量型矩阵,计算原始数据集的信息熵,按最后一列计算,最后一列是标签 :return: 所有类别的信息熵 ''' numEntries = len(dataSet) #计算矩阵行数 labelCounts = {} # 存放每一个标签及数量 for featVec in dataSet: # 对于矩阵的每一行数据 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 # 求期望=∑(每个类别概率*每个类别信息) log值表示这个分类对应的信息 shannonEnt -= prob * log(prob,2) return shannonEnt def splitDataSet(dataSet, axis, value): ''' 根据某一列的值来划分数据集 :param dataSet:待划分的数据集 :param axis: 列号,划分数据集的特征在哪一列 :param value:某列对应值 :return:retDataSet 去除了划分特征的那一列剩下的数据 ''' retDataSet = [] for featVec in dataSet: if featVec[axis] == value: reducedFeatVec = featVec[:axis] #chop out axis used for splitting reducedFeatVec.extend(featVec[axis+1:]) # extend 组成的list里边没有list,list全部展开 retDataSet.append(reducedFeatVec) # extend 组成的list里边有list,list保持 return retDataSet def chooseBestFeatureToSplit(dataSet): ''' 给定一个数据集,(带有条件和结果特征的数据集合),得到最佳的分类是第几个特征,从0开始 :param dataSet:最后一列是结果特征,前几列是条件列特征,其他列是标量型的数据,数据集都是标量型 :return: ''' numFeatures = len(dataSet[0]) - 1 #特征的个数,减1是因为数据集的最后一列是标签 baseEntropy = calcShannonEnt(dataSet) #计算原始数据集的信息熵,按最后一列计算 bestInfoGain = 0.0; bestFeature = -1 for i in range(numFeatures): #遍历所有的数据特征 featList = [example[i] for example in dataSet]# 该特征的所有值 uniqueVals = set(featList) #该特征所有值去重 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 #信息增益等于原始数据集的熵减去新的熵(无需度的减少) if (infoGain > bestInfoGain): #比较当前信息增益和最佳增益的大小 bestInfoGain = infoGain #if better than current best, set to best bestFeature = i return bestFeature #得出最佳增益应该是第几个特征,从0开始 def majorityCnt(classList): ''' 投票表决代码,选出出现最多的结果 :param classList: :return: ''' classCount={} for vote in classList: if vote not in classCount.keys(): classCount[vote] = 0 classCount[vote] += 1 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] def createTree(dataSet,labels): ''' 构造决策树,生成嵌套字典 :param dataSet:对应的含有条件和结果特征的数据集,都是标量型 :param labels:labels是特征列名 :return: ''' classList = [example[-1] for example in dataSet] #结果特征集合 if classList.count(classList[0]) == len(classList): return classList[0]#如果所有的结果特征值都相同,停止生成决策树,返回这个结果特征 if len(dataSet[0]) == 1: #如果只有一个结果特征列了,停止生成决策树,返回比较多的结果特征 return majorityCnt(classList) bestFeat = chooseBestFeatureToSplit(dataSet) #找到最佳的划分条件特征是哪一个特征,列数 bestFeatLabel = labels[bestFeat] #最佳的条件特征标签 myTree = {bestFeatLabel:{}} del(labels[bestFeat]) #删除最佳条件标签剩下的特征标签 featValues = [example[bestFeat] for example in dataSet] #最佳特征标签对应的一列数据的值 uniqueVals = set(featValues) #没有重复的最佳特征标签对应的一列数据的值 for value in uniqueVals: # 对每个值生成决策树 subLabels = labels[:] #拷贝所有标签,为了不与其他标签混淆 myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels) #递归调用,对于每个树分支的值还是一颗树 return myTree def classify(inputTree,featLabels,testVec): ''' ID3决策树分类器 :param inputTree:字典树 :param featLabels:条件特征列表 :param testVec:测试样本列表 :return:结果特征值 ''' firstStr = inputTree.keys()[0] secondDict = inputTree[firstStr] 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 storeTree(inputTree,filename): ''' 持久化存储 :param inputTree: :param filename: :return: ''' import pickle fw = open(filename,'w') pickle.dump(inputTree,fw) fw.close() def grabTree(filename): ''' 从文件获取树字典 :param filename: :return: ''' import pickle fr = open(filename) return pickle.load(fr)
画出决策树的程序
treePlotter.py
# -*- coding: utf-8 -* ''' 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): ''' 获取叶节点的数目 :param myTree:字典结构的树 :return: ''' numLeafs = 0 firstStr = myTree.keys()[0] secondDict = myTree[firstStr] 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 numLeafs += getNumLeafs(secondDict[key]) else: numLeafs +=1 return numLeafs def getTreeDepth(myTree): ''' 获取树的最大深度 :param myTree:字典结构的树 :return: ''' maxDepth = 0 firstStr = myTree.keys()[0] secondDict = myTree[firstStr] 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 thisDepth = 1 + getTreeDepth(secondDict[key]) else: thisDepth = 1 if thisDepth > maxDepth: maxDepth = thisDepth return maxDepth def plotNode(nodeTxt, centerPt, parentPt, nodeType): createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction', xytext=centerPt, textcoords='axes fraction', 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 # ❷(以下两行)计算宽和高 numLeafs = getNumLeafs(myTree) #this determines the x width of this tree depth = getTreeDepth(myTree) firstStr = 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')#画出来图形figure1 背景色白色 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)
算法适用类型:输入输出是标称型或者数值型
结合最优化算法,梯度下降法。梯度是当前函数在当前自变量X=(x0,y0),(x1,y1)(x2,y2)…),因变量Z上升最快的方向,本质上是一个向量(梯度的方向实际就是函数在此点上升最快的方向)
梯度下降法的详细解释见https://www.jianshu.com/p/c7e642877b0e
最通俗的公式:
α在梯度下降算法中被称作为学习率或者步长,梯度前加一个负号,就意味着朝着梯度相反的方向前进!
###多变量函数的梯度下降
我们假设有一个目标函数!
现在要通过梯度下降法计算这个函数的最小值。我们通过观察就能发现最小值其实就是 (0,0)点。但是接下来,我们会从梯度下降算法开始一步步计算到这个最小值!
我们假设初始的起点为:
初始的学习率为:
函数的梯度为:
进行多次迭代:
我们发现,已经基本靠近函数的最小值点
步长(Learning rate): 步长决定了在梯度下降迭代的过程中,每一步沿梯度负方向前进的长度。
特征(feature): 指的是样本中输入部分
比如2个单特征(一个条件一个结果)的样本
(x^{(0)},y^{(0)}),(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),...,(x^{(m)},y^{(m)})
则第一个样本特征为
(x^{(0)})
第一个样本输出为
(y^{(0)})
假设函数(hypothesis function):
在监督学习中,为了拟合输入样本,而使用的假设函数,记为
h_{(\Theta)}(x)
比如对于单个特征的m个样本
(x(i),y(i))(i=1,2,…m),可以采用拟合函数如下:
h^{(\Theta)}(x)=\Theta_0+\Theta_1x
损失函数(loss function):为了评估模型拟合的好坏,通常用损失函数来度量拟合的程度。损失函数极小化,意味着拟合程度最好,对应的模型参数即为最优参数。在线性回归中,损失函数通常为样本输出和假设函数的差取平方。比如对于m个样本(x(i),y(i))(i=1,2,…m),采用线性回归,损失函数为:
J(\Theta_0,\Theta_1)=\Sigma^m_{i=1}(h_0x^{(i)}-y^{(i)})^2
其中xi表示第i个样本特征,yi表示第i个样本对应的输出,
h_{(\Theta)}(x)
为假设函数。
我们需要定义一个代价函数,在此我们选用均方误差代价函数
此公示中
m是数据集中点的个数
½是一个常量,这样是为了在求梯度的时候,二次方乘下来就和这里的½抵消了,自然就没有多余的常数系数,方便后续的计算,同时对结果不会有影响
y 是数据集中每个点的真实y坐标的值,h 是我们的预测函数,根据每一个输入x,根据Θ 计算得到预测的y值,即
我们可以根据代价函数看到,代价函数中的变量有两个,所以是一个多变量的梯度下降问题,求解出代价函数的梯度,也就是分别对两个变量进行微分
明确了代价函数和梯度,以及预测的函数形式。我们就可以开始编写代码了。但在这之前,需要说明一点,就是为了方便代码的编写,我们会将所有的公式都转换为矩阵的形式,python中计算矩阵是非常方便的,同时代码也会变得非常的简洁。
为了转换为矩阵的计算,我们观察到预测函数的形式
我们有两个变量,为了对这个公式进行矩阵化,我们可以给每一个点x增加一维,这一维的值固定为1,这一维将会乘到Θ0上。这样就方便我们统一矩阵化的计算
然后我们将代价函数和梯度转化为矩阵向量相乘的形式
在python中的梯度下降法代码:
import numpy as np # Size of the points dataset. m = 20 # Points x-coordinate and dummy value (x0, x1). X0 = np.ones((m, 1)) X1 = np.arange(1, m+1).reshape(m, 1) X = np.hstack((X0, X1)) # Points y-coordinate y = np.array([ 3, 4, 5, 5, 2, 4, 7, 8, 11, 8, 12, 11, 13, 13, 16, 17, 18, 17, 19, 21 ]).reshape(m, 1) # The Learning Rate alpha. alpha = 0.01 # 求误差函数 def error_function(theta, X, y): '''Error function J definition.''' diff = np.dot(X, theta) - y #参数矩阵,是一个n行一列的矩阵,n是特征维度个数 return (1./2*m) * np.dot(np.transpose(diff), diff) # 求梯度 def gradient_function(theta, X, y): '''Gradient of the function J definition.''' diff = np.dot(X, theta) - y #误差 return (1./m) * np.dot(np.transpose(X), diff) #梯度 # 梯度下降法求梯度 def gradient_descent(X, y, alpha): '''Perform gradient descent.''' theta = np.array([1, 1]).reshape(2, 1) #参数矩阵 gradient = gradient_function(theta, X, y) #梯度 while not np.all(np.absolute(gradient) <= 1e-5): theta = theta - alpha * gradient gradient = gradient_function(theta, X, y) #求梯度 return theta optimal = gradient_descent(X, y, alpha) print('optimal:', optimal) print('error function:', error_function(optimal, X, y)[0,0])
运行代码,计算得到的结果如下
得出拟合曲线
自己编写的代码:
#!/usr/bin/python # -*- coding: UTF-8 -*- import numpy as np import matplotlib.pyplot as plt # 特征样本,结果样本 def createData(m): X0=np.ones((m,1)) X1=np.arange(1,m+1).reshape(m,1) #两列实际上是单变量 factor=np.hstack((X0,X1)) label=np.array([ 3, 4, 5, 5, 2, 4, 7, 8, 11, 8, 12, 11, 13, 13, 16, 17, 18, 17, 19, 21 ]).reshape(m, 1) return factor,label,X1 #误差函数矩阵 def erroFunction(theta,X,Y): #theta是参数矩阵 return np.array((1.0/2*X.shape[0])*np.dot(np.dot(X,theta)-Y).T,(np.dot(X,theta)-Y)) # 梯度矩阵 def gradFunction(theta,X,Y): return (1.0/X.shape[0])*np.dot(np.transpose(X),(np.dot(X,theta)-Y)) # 梯度下降法求梯度 def gradientDescent(theta,X,Y,alpha=0.01):#alpha是学习率 gradient=gradFunction(theta,X,Y) while not np.all(np.absolute(gradient))<=1e-5: theta=theta-alpha*gradient #让参数矩阵尽快达到最值 gradient=gradFunction(theta,X,Y) return theta X, Y,X1 = createData(20) theta=np.array([1,1]).reshape(2,1) #初始参数矩阵 fig=plt.figure() ax=fig.add_subplot(111) ax.scatter(X1,Y,marker='o',color='red') theta=gradientDescent(theta,X,Y) pridict=np.dot(X,theta) ax.scatter(X1,pridict,color='b',marker='^') print '估计参数;\n'+str(theta) plt.show()
Logistic算法是在梯度算法的基础上引入Sigmoid函数,这个函数是一个类似脉冲的函数,如果结果只有两个标签,输入一个值后超过0.5的被认为是标签1,否则是标签0
def sigmoid(inX): return 1.0/(1+exp(-inX)) #!/usr/bin/python # -*- coding: utf-8 -*- import numpy as np ''' 逻辑回归代码:输入是数值型,输出是1 0数值标签 ''' # 定义Sigmoid函数,预测值函数 def Sigmoid(x): return 1.0/(np.exp(-x)+1) # 从文件中加载数据,输出是np.arr矩阵,条件样本在每行增加一列,每个数都是1 def LoadData(): fr=open('D:\\PythonProject\\PythonVSTest\\test\\Ch05\\testSet.txt','r') X=[] Y=[] for line in fr.readlines(): lineArr=line.strip().split() #数组list 3 X.append([1.0,float(lineArr[0]),float(lineArr[1])]) #list Y.append([float(lineArr[2])]) #list inputX=np.array(X) outputY=np.array(Y) return inputX,outputY inputX,outputY=LoadData() def GetGrad(X,Y,weight): #预测值矩阵(m*1) Sigmoid(X*weight) h=Sigmoid(np.dot(X,weight)) #np.dot(X,weight)是预测值矩阵(m*1),预测值经过Sigmoid函数得到预测标签 #误差矩阵(m*1)error=(X*weight-Y) error=h-Y #daijiaFunction=(1.0/2*X.shape[0])*np.dot(error.T,error) #求梯度矩阵(n*1) X.T*error*(1/m) grad=(1.0/X.shape[0])*np.dot(X.T,error) return grad # 梯度逻辑回归算法,求参数矩阵weight(n*1) def gradDescentLogics(X,Y,alpha=0.001): m,n=X.shape #参数矩阵(n*1) weight=np.ones((n,1)) #n行1列参数(权重)矩阵 #求梯度矩阵(n*1) X.T*error*(1/m) grad=GetGrad(X,Y,weight) # grad=np.dot(X.T,error) #梯度求最值 while not np.all(np.absolute(grad))<1e-2: #求梯度矩阵(n*1) X.T*error*(1/m) grad=GetGrad(X,Y,weight) weight=weight-alpha*grad return weight #另一种循环固定次数 #cycle=500 #i=0 #while i<=cycle: # error=Sigmoid(np.dot(X,weight))-Y # weight=weight-alpha*np.dot(X.T,error) # i=i+1 #return weight weight=gradDescentLogics(inputX,outputY) print (weight)
#!/usr/local/python3/python # -*-coding:utf-8-*- import os import sys from numpy import * import time import matplotlib.pyplot as plt ##kmeans算法的实现: #伪代码 # 创建k个点作为初始的质心点(随机选择) # 当任意一个点的簇分配结果发生改变时 # 对数据集中的每一个数据点 # 对每一个质心 # 计算质心与数据点的距离 # 将数据点分配到距离最近的簇 # 对每一个簇,计算簇中所有点的均值,并将均值作为质心 ##数据加载,将数据转化成矩阵 def loadDataSet(filename): dataMat=[] #加载数据 fr=open(filename) for line in fr.readlines(): #字符串去掉开头和结尾的空格,并以'\t'为分割,变成list(列表) newline=line.strip().split('\t') newLine=list(map(float,newline)) #不是扩展,而是append,扩展和追加的区别 dataMat.append(newLine) return mat(dataMat) # print(loadDataSet(r'C:\Users\Administrator\Desktop\text.txt')) dataSet=loadDataSet(r'C:\Users\Administrator\Desktop\text.txt') # print(dataSet) ##计算欧式距离 def oushiJuli(A,B): return sqrt(sum(power(A-B,2))) ##构建初始化聚集中心矩阵也就是求取k个质心,一共有k个分类,对应k个聚集中心,k个质心 def randCent(dataSet,k): #求取要分析矩阵(还不是矩阵是array列表)的行列,并取出其中的列n #其中行数是数据的总数目,列数是点坐标的维数 n=shape(dataSet)[1] #初始化矩阵(用mat方法),k行,n列 centroids=mat(zeros((k,n))) for j in range(n): ##求取原始数据每一列的最大和最小值 minJ=min(dataSet[:,j]) maxJ=max(dataSet[:,j]) rangeJ=float(maxJ-minJ) ##矩阵相加,求取质心 centroids[:,j]=minJ+rangeJ*random.rand(k,1) return centroids ##kmens算法主函数 def kMeans(dataSet,k,distMeans=oushiJuli,createCent=randCent): #球数据的总数目m m=shape(dataSet)[0] #族类矩阵(所有样本的质心归属矩阵):存放每一个数据属于哪类及距离 clusterAssment=mat(zeros((m,2))) #初始化质心 centroids=createCent(dataSet,k) #群族改变 clusterChanged=True while clusterChanged: #族群改变标志设为假 clusterChanged=False #对每一个数据集中的数据点 for i in range(m): #初始化欧式距离的最小值,及最小距离对应的类 minDist=inf minIndex=-1 #对每一个质心 for j in range(k): #计算每个点到质心的距离 distJ=distMeans(centroids[j,:],dataSet[i,:]) #如果计算出的欧氏距离比最小距离还小 if distJ<minDist: #把最小距离赋值为计算的欧式距离,顺带的把质心的标记j赋值给minIndex minDist=distJ minIndex=j #如果族类矩阵记录的样本归属质心不是距离最小的j if clusterAssment[i,0]!=minIndex: #把群族的变化标志位变成真,预示着族类矩阵还要优化 clusterChanged=True #重新记录群族样本的质心归属,和对应的欧式距离 clusterAssment[i,:]=minIndex,minDist**2 #族群改变前,打印质心 # print(centroids) #群族改变,重新计算质心 for cent in range(k): #nonzero是求不是零(为真)的索引,clusterAssment记录所有样本中质心的归属j(0<j<k),A是将矩阵中numpy的matrix转化成array #matrix具有array的所有属性。nonzero(clusterAssment[:, 0].A == cent(这是个tuple对象)如果是对第一个质心cent=0,那么这个式子就是表示 #从记录样本质心标记中找出所有该类质心的点的位置, 用dataSet[nonzero(clusterAssment[:, 0].A == cent)[0]] # (tuple第一个值nonzero(clusterAssment[:, 0].A == cent)[0]表示可以取出来1第一行,如果不加[0],就是4,5表示4行5列,表示一个具体的行列值) # 可以取出来所有属于该质心的行,如果后边不加[0],就只可以可以取出第一列,样本的横坐标。可以试一下 ptsInClust = dataSet[nonzero(clusterAssment[:, 0].A == cent)[0]] #axis=0代表对列求平均值 centroids[cent, :] = mean(ptsInClust, axis=0) #返回质心,族类矩阵 return centroids, clusterAssment #如果将样本分成4类打印结果 # print(kMeans(dataSet,4)[1]) centRoids,assment = kMeans(dataSet,4) fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(dataSet[:, 0].tolist(), dataSet[:, 1].tolist(), c='blue') ax.scatter(centRoids[:, 0].tolist(), centRoids[:, 1].tolist(), c='red', marker='+', s=70) plt.show()
# coding:utf-8 from sklearn import linear_model import svmMLiA as svm import numpy as np #线性回归,输入输出都是数值型的 linear = linear_model.LinearRegression(normalize=False) #归一标准化化 x_train_list,y_train_list=svm.loadDataSet('testSet.txt') x_train=np.array(x_train_list) y_train=np.array(y_train_list) linear.fit(x_train,y_train) print linear.score(x_train,y_train) #分类器得分 # 斜率和截距 print('Coefficient: \n', linear.coef_) print('Intercept: \n', linear.intercept_) #预测输出 predicted= linear.predict(np.array([[2,1]])) print predicted #逻辑回归解决2分类问题,输入是数值型,输出是0或者1标签 from sklearn.linear_model import LogisticRegression x_train_list,y_train_list=svm.loadDataSet('testLogistic.txt') x_train=np.array(x_train_list) y_train=np.array(y_train_list) model = LogisticRegression() model.fit(x_train, y_train) print model.score(x_train, y_train) #Equation coefficient and Intercept print('Coefficient: \n', model.coef_) print('Intercept: \n', model.intercept_) #Predict Output predicted= model.predict(np.array([[-1,8]])) print predicted # coding:utf-8 from sklearn import linear_model import svmMLiA as svm import numpy as np #线性回归,输入输出都是数值型的 linear = linear_model.LinearRegression(normalize=False) #归一标准化化 x_train_list,y_train_list=svm.loadDataSet('testSet.txt') x_train=np.array(x_train_list) y_train=np.array(y_train_list) linear.fit(x_train,y_train) print linear.score(x_train,y_train) #分类器得分 # 斜率和截距 print('Coefficient: \n', linear.coef_) print('Intercept: \n', linear.intercept_) #预测输出 predicted= linear.predict(np.array([[2,1]])) print predicted #逻辑回归解决2分类问题,输入是数值型,输出是0或者1标签 from sklearn.linear_model import LogisticRegression x_train_list,y_train_list=svm.loadDataSet('testLogistic.txt') x_train=np.array(x_train_list) y_train=np.array(y_train_list) model = LogisticRegression() model.fit(x_train, y_train) print model.score(x_train, y_train) #Equation coefficient and Intercept print('Coefficient: \n', model.coef_) print('Intercept: \n', model.intercept_) #Predict Output predicted= model.predict(np.array([[-1,8]])) print predicted # 使用sklearn加载数据集 from distutils.version import LooseVersion as Version from sklearn import __version__ as sklearn_version from sklearn import datasets import numpy as np iris = datasets.load_iris() iris.data # 查看数据 X = iris.data[:, [2, 3]] y = iris.target print('Class labels:', np.unique(y)) # 取百分之70做训练,剩下百分30做预测 if Version(sklearn_version) < '0.18': from sklearn.cross_validation import train_test_split else: from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=0) print X_train.shape, X_test.shape, y_train.shape, y_test.shape # 对特征做标准化 from sklearn.preprocessing import StandardScaler sc = StandardScaler() sc.fit(X_train) print sc.scale_ X_train_std = sc.transform(X_train) X_test_std = sc.transform(X_test) #sklearn中的线性分类器 from sklearn.linear_model import Perceptron # ppn = Perceptron(n_iter=40, eta0=0.1, random_state=0) ppn = Perceptron() ppn.fit(X_train_std, y_train) ppn.coef_ ppn.intercept_ y_pred = ppn.predict(X_test_std) y_pred y_test y_pred == y_test print('Misclassified samples: %d' % (y_test != y_pred).sum()) from sklearn.metrics import accuracy_score print('Accuracy: %.2f' % accuracy_score(y_test, y_pred)) # 逻辑回归 from sklearn import datasets import numpy as np iris = datasets.load_iris() X = iris.data[:,[2,3]] y = iris.target # 训练数据和测试数据分为7:3 x_train,x_test,y_train,y_test =train_test_split(X,y,test_size=0.3,random_state=0) # 标准化数据 from sklearn.preprocessing import StandardScaler sc = StandardScaler() sc.fit(x_train) x_train_std = sc.transform(x_train) x_test_std = sc.transform(x_test) # 绘制决策边界 from matplotlib.colors import ListedColormap import matplotlib.pyplot as plt import warnings def versiontuple(v): return tuple(map(int, (v.split(".")))) def plot_decision_regions(X,y,classifier,test_idx=None,resolution=0.02): # 设置标记点和颜色 markers = ('s','x','o','^','v') colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan') cmap = ListedColormap(colors[:len(np.unique(y))]) # 绘制决策面 x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1 x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1 xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution), np.arange(x2_min, x2_max, resolution)) Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T) Z = Z.reshape(xx1.shape) plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap) plt.xlim(xx1.min(), xx1.max()) plt.ylim(xx2.min(), xx2.max()) for idx, cl in enumerate(np.unique(y)): plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1], alpha=0.8, c=cmap(idx), marker=markers[idx], label=cl) # 高粱所有的数据点 if test_idx: # 绘制所有数据点 if not versiontuple(np.__version__) >= versiontuple('1.9.0'): X_test, y_test = X[list(test_idx), :], y[list(test_idx)] warnings.warn('Please update to NumPy 1.9.0 or newer') else: X_test, y_test = X[test_idx, :], y[test_idx] plt.scatter(X_test[:, 0], X_test[:, 1], c='b', alpha=1.0, linewidth=1, marker='o', s=55, label='test set') # 应用Logistics回归模型 from sklearn.linear_model import LogisticRegression lr = LogisticRegression(C=1000.0,random_state=0) lr.fit(x_train_std,y_train) X_combined_std = np.vstack((x_train_std, x_test_std)) y_combined = np.hstack((y_train, y_test)) plot_decision_regions(X_combined_std, y_combined, classifier=lr, test_idx=range(105,150)) plt.xlabel('petal length [standardized]') plt.ylabel('petal width [standardized]') plt.legend(loc='upper left') plt.tight_layout() plt.show() if Version(sklearn_version) < '0.17': lr.predict_proba(X_test_std[0, :]) else: lr.predict_proba(X_test_std[0, :].reshape(1, -1)) lr.predict_proba(X_test_std[0, :]) #来谈谈过拟合/overfitting 与 正则化/regularization #正则化L1 和L2 L1截断,会产生很多0,使矩阵稀疏;L2是缩放,把权重缩放到很小。 from sklearn.svm import SVC svm = SVC(kernel='linear', C=1.0, random_state=0) svm.fit(X_train_std, y_train) X_combined_std = np.vstack((x_train_std, x_test_std)) y_combined = np.hstack((y_train, y_test)) plot_decision_regions(X_combined_std, y_combined, classifier=svm, test_idx=range(105, 150)) plt.xlabel('petal length [standardized]') plt.ylabel('petal width [standardized]') plt.legend(loc='upper left') plt.tight_layout() # plt.savefig('./figures/support_vector_machine_linear.png', dpi=300) plt.show()
加载数据集
# coding: utf-8
from sklearn.datasets import load_iris,fetch_20newsgroups,load_boston
from sklearn.model_selection import train_test_split
iris_data = load_iris()
x_train,x_test,y_train,y_test = train_test_split(iris_data.data,iris_data.target,test_size=0.3)
#print(x_train,x_test,y_train,y_test)
boston = load_boston()
newsData = fetch_20newsgroups(data_home='D:\data',subset='all')
#print(boston.data,boston.target)
#print(newsData.data,newsData.target)
print(len(newsData.data))
print(newsData.data[0])
print(newsData.filenames)
print(newsData.target)
特征工程:sklearn对特征进行提取 文本特征抽取
# coding:utf-8 import pandas as pd import numpy as np from sklearn.feature_extraction import DictVectorizer #字典特征抽取 from sklearn.feature_extraction.text import CountVectorizer #文本特征抽取 from sklearn.feature_extraction.text import TfidfVectorizer #tf idf特征提取 import jieba def DictVec(): ''' 字典数据抽取,将标称型转化成数值型的数据表 :return None ''' instances = [{'city': '北京','temperature':100},{'city': '上海','temperature':60}, {'city': '深圳','temperature':30}] dict=DictVectorizer(sparse=False) #不用sparse矩阵 data=dict.fit_transform(instances) #返回sparse矩阵 scipy中的矩阵 节约内存 方便读取处理 而在numpy中式ndarray的矩阵 print(dict.get_feature_names()) #打印特征名 print(dict.inverse_transform(data)) # 返回原来数据 print(data) #打印提取的特征数据,采用ONE-hot编码,将类别编码转化成one-hot编码 return None def CountTextEnVec(): ''' 对文本进行提取特征,用于文本分类,情感分析,只能用于英文。中文的话先要进行分词用空格分隔,统计步骤: 1.统计所有文章中所有的词,重复的次不计数,只算一次,次的列表,单个字母不统计 2 对步骤1词的列表统计次数 ''' cv=CountVectorizer() data =cv.fit_transform(["life is short,i like python hehe haha hehe","life is too long,i dislike python"]) print(cv.get_feature_names()) print(data.toarray()) return None def CutWord(): ''' 中文分词 ''' c1=jieba.cut('今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。') c2=jieba.cut('我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。') c3=jieba.cut('如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。') lc1=list(c1) lc2=list(c2) lc3=list(c3) rc1=' '.join(lc1) rc2=' '.join(lc2) rc3=' '.join(lc3) return rc1,rc2,rc3 def CountTextZhVec(): ''' 中文分词的特征值提取 ''' cv=CountVectorizer() rc1,rc2,rc3=CutWord() print (rc1,rc2,rc3) data =cv.fit_transform([rc1,rc2,rc3]) print(cv.get_feature_names()) print(data.toarray()) return None def TfIdf(): ''' 使用log(tf*idf)的大小作为词的重要程度的判定 ,tf叫term frequency 词语出现频率 idf inverse document frequency 反向文档频率=总文档数/该词文档数。原理如果一个 词在一个文档出现频繁,而在另一个文档出现不频繁,那么该词重要度高,用于文本分类 ''' tf=TfidfVectorizer() rc1,rc2,rc3=CutWord() print (rc1,rc2,rc3) data =tf.fit_transform([rc1,rc2,rc3]) print(tf.get_feature_names()) print(data.toarray()) return None if __name__=="__main__": #DictVec() #CountTextEnVec() #CountTextZhVec() TfIdf()
sklearn数据预处理:标准化和归一化数据
# coding:utf-8 ''' @auter;menghui.zhao @description: 1.归一化数据,主要利用sklearn.preprocessing 中的MinMaxScaler最大最小缩放,MinMaxScaler(feature_range(0,1)...) feature_range指定缩小范围,目的是使一个特征不会对结果产生影响 min是样本中最小值,max是样本中最大值,注意在数据流场景下最大值 最小值是变化的,另外,最大值与最小值非常容易受异常点影响, 所以这种方法鲁棒性较差,只适合传统精确小数据场景X′=(x-min)/(max-min) 2.标准化数据:X′=(x-μ)/σ,将原始数据的每一列变成均值为0,标准差为1的数据 其中\μ是样本的均值,σ是样本的标准差,它们可以通过现有的样本进行估计, 在已有的样本足够多的情况下比较稳定,适合嘈杂的数据场景,有一定的数据量 3.缺失值根据实际情况进行删除(如果每列或者每行缺失值达到一定比例)或者插补还可以使用pandas (中位数、平均值等,按列) Imputer(missing_values='NaN',strategy='mean',axix=0) Imputer.fit_transfornm(),数据类型必须是np.nan float 将特殊字符替换成Nan cancelData.replace(to_replace='?',value=np.nan) 去掉nan值cancelData.dropna() ''' import numpy as np from sklearn.preprocessing import MinMaxScaler #最大最小缩放,归一化 from sklearn.preprocessing import StandardScaler #标准化 from sklearn.preprocessing import Imputer #缺失值处理 def normalization(): ''' 归一化数据 ''' mm=MinMaxScaler(feature_range=(2,3)) data=mm.fit_transform([[90,2,10,40],[60,4,15,45],[75,3,13,46]]) print (data) return None def standard(): ''' 标准化数据 ''' std=StandardScaler() data=std.fit_transform([[90,2,10,40],[60,4,15,45],[75,3,13,46]]) print (data) return None def dealNanData(): ''' 缺失数据处理 ''' im=Imputer(missing_values='NaN',strategy='mean',axis=0) data=im.fit_transform([[np.nan,2,10,40],[60,4,15,45],[75,3,13,46]]) print (data) return None if __name__=='__main__': #normalization() #standard() dealNanData()
sklearn数据降维
# coding:utf-8 ''' 1.方差特征过滤 2.PCA:特征数量上百的时候,考虑数据的简化,数据会改变,特征会减少 n_components 0.9-0.95 经验信息保存的百分比 如果是整数 表示减少到的特征数量 3.神经网络 4.其他方法 ''' from sklearn.feature_selection import VarianceThreshold #方差过滤的方式选择特征 from sklearn.decomposition import PCA def VarFeatureFilter(): var=VarianceThreshold(threshold=0.0) #将方差小于该阈值的一列特征去掉 data=var.fit_transform([[1,2,3],[1,4,5],[1,2,4]]) print data return None def PcaFeatureFilter(): pca=PCA(n_components=0.9) data=pca.fit_transform([[4,2,3,9],[5,4,5,3.3],[1,2,4,7]]) print data return None if __name__=='__main__': #VarFeatureFilter() PcaFeatureFilter()
使用PCA进行降维的例子
# coding : utf-8 import pandas as pd from sklearn.decomposition import PCA ''' 多个表利用pandas串表,然后利用PCA进行分析 ''' #读取数据表 priror = pd.read_csv('./data/priror.csv') products = pd.read_csv('./data/products.csv') order = pd.read_csv('./data/order.csv') ailes = pd.read_csv('./data/ailes.csv') # 利用pandas合并表 _mg = pd.merge(priror,products,open=['product_id','product_id']) _mg = pd.merge(_mg,order,open=['order_id','order_id']) mdata = pd.merge(_mg,ailes,open=['ailes_id','ailes_id']) print(mdata.head(10)) #建立行列数据,交叉表(特殊的分组) cross = pd.crosstab(mdata['user_id'],mdata['ailes']) pca = PCA(n_components=0.9) finalData = pca.fit_transform(cross)
sklearn.datasets
datasets.load()
获取小规模数据集
datasets.fetch(data_home=None)
需要从a网络上获取大规模,data_home是数据集下载目录,默认是~/scikit_learn_data/
load和fetch默认的返回类型是datasets.base.Bunch(字典形式)
data 是特征数据,是numpy.ndarray二维数组;
target是标签数组,是numpy.ndarray一维数组
DESCR: 数据描述
feature_names:特征名
target_names:标签名
sklearn.model_section.train_test_split(*arrays,**options)
*array是可变列表,数据特征值和数据目标值:即datasets.data,datasets.target目标值list
**options是数据参数,test_size=0.25(测试数据的占比)
返回数据(x_train,y_train,x_test,y_test)
# coding: utf-8
from sklearn.datasets import load_iris,fetch_20newsgroups,load_boston
from sklearn.model_selection import train_test_split
iris_data = load_iris()
x_train,x_test,y_train,y_test = train_test_split(iris_data.data,iris_data.target,test_size=0.3)
#print(x_train,x_test,y_train,y_test)
boston = load_boston()
newsData = fetch_20newsgroups(data_home='D:\data',subset='all')
#print(boston.data,boston.target)
#print(newsData.data,newsData.target)
print(len(newsData.data))
print(newsData.data[0])
print(newsData.filenames)
print(newsData.target)
K近邻,k个最近的大多属于哪一类就算哪一类,欧式距离,这种算法是需要进行标准化处理的,优点简单,对k敏感,性能需求高,数据集的knn算法
#!/usr/bin/python # -*- coding: UTF-8 -*- from sklearn.neighbors import KNeighborsClassifier #导入knn分类器 from sklearn.preprocessing import StandardScaler #标准化 import pandas as pd from sklearn.model_selection import train_test_split def knn(): # 读取数据 datasets=pd.read_csv('E:\\人工智能教程\\knnDatasets\\train.csv') print (datasets.head(10)) # 处理数据 data=datasets.query('x>1.0&x<1.5&y>2.5&y<2.75') #缩小x y time_value=pd.to_datetime(data['time'],unit='s') # 处理时间 #print(time_value) # 把日期转化成字典格式 time_value=pd.DatetimeIndex(time_value) #print(time_value) # 构造新特征 data['day']=time_value.day data['hour'] = time_value.hour data['weekday'] = time_value.weekday print(data.head(10)) # 把时间特征删除 data=data.drop(['time'],axis=1) #data = data.drop(['row_id'], axis=1) # 把小于n个目标的位置删除 place_count=data.groupby('place_id').count() tf=place_count[place_count.row_id>3].reset_index() data=data[data['place_id'].isin(tf.place_id)] # 去除无关的row_id data = data.drop(['row_id'], axis=1) #取出特征值和目标值 y=data['place_id'] x=data.drop(['place_id'],axis=1) # 标准化数据 std=StandardScaler() # 进行分割 x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.25) # 对训练集和测试集的特征值进行标准化 x_train=std.fit_transform(x_train) x_test=std.fit_transform(x_test) print(data.head(10)) #k近邻算法 knn=KNeighborsClassifier(n_neighbors=5) knn.fit(x_train, y_train) # 预测值 y_pridict=knn.predict(x_test) # 准确度 print(knn.score(x_test,y_test)) return None if __name__=='__main__': knn()
朴素的含义是条件独立的意思。
# coding:utf-8 from sklearn.datasets import fetch_20newsgroups from sklearn.model_selection import train_test_split from sklearn.feature_extraction.text import TfidfVectorizer # 文本特特征抽取 from sklearn.naive_bayes import MultinomialNB # 朴素贝叶斯算法 from sklearn.metrics import classification_report #指标 def bayes(): ''' 朴素贝叶斯算法 :return: ''' news = fetch_20newsgroups(data_home='D:\data', subset='all') x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.3) # 对数据集进行特征抽取 tf = TfidfVectorizer() # 训练集和测试集中的词按重要性进行统计 x_train = tf.fit_transform(x_train) # print(tf.get_feature_names()) x_test = tf.transform(x_test) # 进行朴素贝叶斯算法的预测,拉普拉斯平滑系数默认设置为1 mlt=MultinomialNB(alpha=1.0) mlt.fit(x_train,y_train) y_pridict=mlt.predict(x_test) print('预测的文章列表:',y_pridict) # 得出准确率 print('准确率:',mlt.score(x_test,y_test)) print('每个类别的精确率和召回率:\n',classification_report(y_test,y_pridict,target_names=news.target_names)) return None if __name__ == '__main__': bayes()
分类模型评估指标:
recall 体现了分类模型HH对正样本的识别能力,recall 越高,说明模型对正样本的识别能力越强,precision 体现了模型对负样本的区分能力,precision越高,说明模型对负样本的区分能力越强。F1-score 是两者的综合。F1-score 越高,说明分类模型越稳健。比如我们常见的雷达预警系统,我们需要对雷达信号进行分析,判断这个信号是飞行器(正样本)还是噪声 (负样本), 很显然,我们希望系统既能准确的捕捉到飞行器信号,也可以有效地区分噪声信号。所以就要同时权衡recall 和 precision这两个指标,如果我们把所有信号都判断为飞行器,那 recall 可以达到1,但是precision将会变得很低(假设两种信号的样本数接近),可能就在 0.5 左右,那F1-score 也不会很高。
接口:ssklearn.model_selection.GridSearchCV(estimator,param_grid=None,cv=None)
输入参数:
结果
# coding:utf-8 from sklearn.datasets import fetch_20newsgroups from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.feature_extraction.text import TfidfVectorizer # 文本特特征抽取 from sklearn.naive_bayes import MultinomialNB # 朴素贝叶斯算法 from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import classification_report # 指标 def Gridcv(): ''' 网格搜索 :return: ''' news = fetch_20newsgroups(data_home='D:\data', subset='all') x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.3) # 对数据集进行特征抽取 tf = TfidfVectorizer() # 训练集和测试集中的词按重要性进行统计 x_train = tf.fit_transform(x_train) # print(tf.get_feature_names()) x_test = tf.transform(x_test) # knn算法 knn = KNeighborsClassifier(n_neighbors=5) # 进行网格搜索 # 构造参数值进行搜索 param = {'n_neighbors': [3, 5, 10]} # 一般cv=10 gc = GridSearchCV(knn, param_grid=param, cv=2) gc.fit(x_train,y_train) y_pridict=gc.predict(x_test) # 预测准确率 print('在测试集上的准确率:',gc.score(x_test,y_test)) print('预测输出:',y_pridict) print('在交叉验证上的最好的结果:',gc.best_score_) print('最好的参数模型:',gc.best_estimator_) print('每个超参数每次交叉验证的结果:',gc.cv_results_) return None if __name__ == '__main__': Gridcv()
信息熵:
E = -Σp(x)logp(x)
信息熵越大不确定性越强
信息增益:表示信息不确定性减少的程度,信息增益越大作为最新的决策节点。ID3是信息增益最大的原则,C4.5是信息增益比最大,CART 1. 回归树:平方误差最小 2. 分类树:基尼系数最小原则,划分更加细致,sklearn默认划分依据
优点:企业可视化,需要较少的数据,不需要归一标准化
缺点:树过于复杂,过拟合
接口:sklearn.tree.DecisionClassifer(criterion=‘gini’,max_depth=None,random_state=None,min_samples_split=2,min_samples_leaf=1)
输入参数:
# coding : utf-8 import pandas as pd from sklearn.feature_extraction.dict_vectorizer import DictVectorizer from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier,export_graphviz def decision_tree(): # 读取泰坦尼克号数据 rawData = pd.read_csv('http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt') # 处理数据找出特征值和目标值 target = rawData['survived'] data = rawData[['pclass', 'age', 'sex']] # 缺失值处理 data['age'].fillna(data['age'].mean(),inplace=True) # 分割数据 x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.25) dicVect = DictVectorizer(sparse=False) x_train = dicVect.fit_transform(x_train.to_dict(orient='records')) x_test = dicVect.transform(x_test.to_dict(orient='records')) # 使用决策树 tree=DecisionTreeClassifier(max_depth=5) print(dicVect.get_feature_names()) # 导出决策树的结构 tree.fit(x_train,y_train) export_graphviz(tree,out_file='./tree.dot',feature_names=list(dicVect.get_feature_names())) print('预测值:',tree.predict(x_test)) print('准确度:',tree.score(x_test,y_test)) return None if __name__ == '__main__': decision_tree()
安装graphviz
集成学习:建立几个模型组合来解决单一预测问题,生成多个分类器/模型,各自独立学习和做出预测,最后在结合,优于任何一个单分类做出的预测
随机森林是包含多个决策树的分类器,效果优于单个树,输出类别是由多个树输出类别的众数决定
随机森林是比较好的机器学习方法,可以用于特征数和样本数的数据集上,不需要降维
api接口:
sklearn.ensemble.RandomForestClassifier(n_estimators=10,criterion=‘gini’,max_depth=None,bootstrap=True,random_state=None)
# coding:utf-8 from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier from sklearn.feature_extraction import DictVectorizer from sklearn.model_selection import train_test_split,GridSearchCV import pandas as pd def random_forest(): # 读取泰坦尼克号数据 rawData = pd.read_csv('http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt') # 处理数据找出特征值和目标值 target = rawData['survived'] data = rawData[['pclass', 'age', 'sex']] # 缺失值处理 data['age'].fillna(data['age'].mean(), inplace=True) # 分割数据 x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.25) dicVect = DictVectorizer(sparse=False) x_train = dicVect.fit_transform(x_train.to_dict(orient='records')) x_test = dicVect.transform(x_test.to_dict(orient='records')) # 使用随机森林 rf=RandomForestClassifier() params={'n_estimators':[100,120,300,500,800,1200],'max_depth':[5,8,15,30]} # 网格搜索与交叉验证 gc=GridSearchCV(rf,param_grid=params,cv=2) gc.fit(x_train,y_train) print('准确率',gc.score(x_test,y_test)) print('选择的参数模型',gc.best_params_) return None if __name__=='__main__': random_forest()
目标值是连续型的数据就用回归算法
回归性能评估:采用均方误差评价
Δ = \frac{1}{m}Σ^m_{i=1}(y^i-\overline{y})
API
sklearn.metrics.mean_squared_error(y_true,y_pred)
算法的过拟合和欠拟合
欠拟合:模型误差大,算法复杂度小,考虑因素小,在训练集和训练集外均不能获得好的拟合效果,可以增加数据的特征数量
过拟合:模型误差大,算法复杂度大,考虑太多因素,本来不是分类的因素考虑了,在训练集上效果好,在训练集以外不能很好拟合数据,过拟合。可以去消除一些关联性强的数据特征(过滤低方差特征 嵌入式如正则化 减少高次项的影响,缩小高次项的权重; 决策树和神经网络)。网格搜索交叉验证的结果即训练集和测试集的结果
针对算法优化策略,使误差(损失)函数最小
w= (X^TX)^{-1}X^Ty
其中X为特征值矩阵,y为目标值矩阵。速度太慢
API
sklearn.linear_model.LinearRegression
正规方程:coef 回归系数 容易出现过拟合
sklearn.linear_model.SGDRegression
梯度下降 数据量大时使用 coef 回归系数
API
sklearn.linear_model.Ridge(alpha=1.0)
alpha: 正则化力度 值越大权重越小趋近于0 [0-1] 小数 [1-10] 整数
coef_:回归系数
案例:
# coding:utf-8 from sklearn.datasets import load_boston from sklearn.linear_model import LinearRegression, SGDRegressor,Ridge from sklearn.preprocessing import MinMaxScaler, StandardScaler from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.ensemble import RandomForestClassifier import numpy as np from sklearn.metrics import mean_squared_error def liner(): ''' 线性回归 :return: ''' # 获取数据 boston_data = load_boston() # 分割数据 x_train, x_test, y_train, y_test = train_test_split(boston_data.data, boston_data.target, test_size=0.25) # 标准化 特征值和目标值都需要标准化处理 std_x = StandardScaler() # 特征值 0.19必须转化为二维 x_train = std_x.fit_transform(x_train) x_test = std_x.transform(x_test) std_y = StandardScaler() # 目标值 y_train = std_y.fit_transform(y_train.reshape(-1, 1)) y_test = std_y.transform(y_test.reshape(-1, 1)) # estimator 预测 lr = LinearRegression() # 正规方程求解 lr.fit(x_train, y_train) print(lr.coef_) # 参数,回归系数 # 预测测试集的结果,标准化的数据偏小,需要反标准化 print('正规方程预测价格:', std_y.inverse_transform(lr.predict(x_test))) print('正规方程均方误差',mean_squared_error(std_y.inverse_transform(y_test),std_y.inverse_transform(lr.predict(x_test)))) sgd = SGDRegressor() # 梯度下降求解,sklearn不需要指定学习率 sgd.fit(x_train, y_train) print(sgd.coef_) # 参数,回归系数 # 预测测试集的结果,标准化的数据偏小,需要反标准化 print('梯度下降预测价格:', std_y.inverse_transform(sgd.predict(x_test))) print('梯度下降均方误差',mean_squared_error(std_y.inverse_transform(y_test),std_y.inverse_transform(sgd.predict(x_test)))) rd = Ridge(alpha=1.0) # 岭回归,alpha是回归力度,越大权重越小 ,趋近于0 rd.fit(x_train, y_train) print(rd.coef_) # 参数,回归系数 # 预测测试集的结果,标准化的数据偏小,需要反标准化 print('岭回归预测价格:', std_y.inverse_transform(rd.predict(x_test))) print('岭回归均方误差', mean_squared_error(std_y.inverse_transform(y_test), std_y.inverse_transform(rd.predict(x_test)))) return None if __name__ == '__main__': liner()
from sklearn.externals import joblib
保存:joblib.dump(rf,‘test.pkl’)
加载:estimator=joblib.load(‘test.pkl’)
保存格式:pkl
二分类问题,预测的是一个概率,判别模型。已经带有正则化的过程,有正则化力度系数。解决过拟合问题。典形应用例如广告被点击的概率 ,是否垃圾邮件,是否患病,金融诈骗,虚假账号的判定。简单速度快。基于线性回归。朴素贝叶斯解决多分类,文本分类,没有系数,基于先验概率,生成模型,应用场景的区别。得出的结果都有概率解释。 sigmoid函数的输出值时[0-1],默认0.5作为阈值,sigmoid函数如下
z=\frac{1}{1+e^{-x}}
损失误差函数(对数似然函数):
cos(h_θ(x),y)=
\begin{cases}-log(h_θ(x)),&if&y=1
\\-log(1-h_θ(x)),&if&y=0 \end{cases}
均方误差不存在多个最低点,对数似然利用梯度下降法求解,存在局部最优解。利用随机初始化,多次比较最小值,或者调整学习率去优化改善局部最优解的问题 。sklearn已经考虑了这些问题。
完整的损失函数:
cos(h_θ(x),y)=Σ^m_{i=1}-y_ilog(h_θ(x))-(1-y_i)log(1-h_θ(x)))
API
sklearn.linear_model.LogisticRegression(penalty=‘12’,C=1.0)
在样本中哪个类比少,就把那个类别作为目标类别,即正样本
例如如果癌症样本少,就把预测癌症作为正样本。癌症预测样本
癌症数据的第一类是id,所以去掉
pandas.read_csv(’’,names=column_names) names是指定列的名字
# coding :utf-8 import pandas as pd import numpy as np from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn.metrics import mean_squared_error, classification_report def Logstic(): # 自定义列名 columns = ['Sample code number', 'Clump Thickness ', 'Uniformity of Cell Size ', 'Uniformity of Cell Shape ', 'Marginal Adhesion', 'Single Epithelial Cell Size ', 'Bare Nuclei ', 'Bland Chromatin ', 'Normal Nucleoli ', 'Mitoses ', 'Classes'] cancelData = pd.read_csv('breast-cancer-wisconsin.data', names=columns) # 将特殊字符替换成Nan cancelData = cancelData.replace(to_replace='?', value=np.nan) # 去掉nan值 cancelData = cancelData.dropna() data = cancelData[columns[1:10]] target = cancelData[columns[10]] # 进行数据分割 x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.25) # 线性回归需要标准化处理 x_std = StandardScaler() x_train = x_std.fit_transform(x_train) x_test = x_std.transform(x_test) # 二分类,分类结果不用特征化,正则化需要调节超参数 lg = LogisticRegression(C=1.0) lg.fit(x_train, y_train) print('回归系数',lg.coef_) # 回归系数 y_pre = lg.predict(x_test) print('预测结果', y_pre) print('准确率', lg.score(x_test, y_test)) # 2对应良性,4对应恶性 print('召回率', classification_report(y_test, y_pre, labels=[2, 4], target_names=['良性', '恶性'])) # print(cancelData.head(10)) return None if __name__ == '__main__': Logstic()
聚类一般在分类之前,聚类效果好坏用轮廓系数表示,外部最大化即族群之间,内部最小化族群内部。 sci取值范围[-1,1]之间,在0以上效果就比较好
API
sklearn.cluster.KMeans(n_clusters=8,init=‘k-means++’)
轮廓系数
from sklearn.metrics import silhouette_score
# coding : utf-8 import pandas as pd from sklearn.decomposition import PCA from sklearn.cluster import KMeans import numpy.matlib.plt as plt from sklearn.metrics import silhouette_score ''' 多个表利用pandas串表,然后利用PCA进行分析 ''' def kmeans(): # 读取数据表 priror = pd.read_csv('./data/priror.csv') products = pd.read_csv('./data/products.csv') order = pd.read_csv('./data/order.csv') ailes = pd.read_csv('./data/ailes.csv') # 利用pandas合并表 _mg = pd.merge(priror, products, open=['product_id', 'product_id']) _mg = pd.merge(_mg, order, open=['order_id', 'order_id']) mdata = pd.merge(_mg, ailes, open=['ailes_id', 'ailes_id']) print(mdata.head(10)) # 建立行列数据,交叉表(特殊的分组) cross = pd.crosstab(mdata['user_id'], mdata['ailes']) pca = PCA(n_components=0.9) finalData = pca.fit_transform(cross) km = KMeans(n_clusters=4) pre = km.fit(finalData) colors=['red','green','white','orange'] color=[colors[i] for i in pre] print('聚类效果',silhouette_score(finalData,pre)) plt.figure(finalData[:,1],finalData[:,2],color=color) return None if __name__ == '__main__': kmeans()
典形应用:图像识别、语音识别、自然语言处理、自动驾驶
突出神经网络:卷积神经网络(图像) 循环神经网络(自然语言处理)官方网站:tensorflow
框架可以分为计算密集型(tensorflow,cpu,gpu)和IO密集型(web,scrapy,django,http,磁盘)
图:默认已经注册,一组表示tf.Operation计算的单位对象和tf.Tensor表示操作之间的流动的数据单元对象
变量是一种op,是一种特殊的张量,能够持久化,默认被训练
# coding:utf-8 import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # 取出警告信息 import tensorflow as tf # 实现一个加法 a = tf.constant(3.0) b = tf.constant(6.0) sum1 = tf.add(a, b) print('图1', a.graph) print('张量a', a) print('图1', sum1.graph) print('op操作sum1', sum1) # op是一个tensor可以重载 var1 = 1 sum1 = var1 + b print('op重载:', sum1) # 默认的图,相当于是分配一个内存 grph = tf.get_default_graph() print('图1', grph) # 使用默认图,只能运行一张图,但可以指定图运行,run可以是一个列表 with tf.Session() as sess: print('图1', sess.graph) print('默认运行图1', sess.run([a, b, sum1])) # print(a, b, sum1) # 创建一个图,包含op运算和tensor,使用上下文环境 g = tf.Graph() with g.as_default(): c = tf.constant(11.0) print('图2', c.graph) # b 实时提供数据 进行训练,占位符 plt = tf.placeholder(tf.float32, [None, 3]) print('placeholder', plt) with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess0: print('placeholder运行', sess0.run(plt, feed_dict={plt: [[1, 2, 3], [4, 5, 6]]})) # 交互式 tf.InteractiveSession() print('eval a', a.eval()) print('eval sum1', sum1.eval()) # config=tf.ConfigProto(log_device_placement=True看到运行设备 with tf.Session(graph=g, config=tf.ConfigProto(log_device_placement=True)) as sess1: print('指定运行图2', sess1.run(c)) # 只要有会话的上下文环境就可以使用eval() print('指定运行图2 eval c', c.eval()) # 静态和动态形状 plt = tf.placeholder(tf.float32, [None, 2]) print(plt) plt.set_shape([3, 2]) # 静态形状只能修改一次,只能修改行数 总共6个数 # plt.set_shape([4,2]) #静态形状只能修改一次 print(plt) plt_reshape = tf.reshape(plt, [2, 3]) # 动态形状数量总数要匹配,可以修改列数 总共6个数 print(plt_reshape) # 变量张量和常数张量 const = tf.constant([1, 2, 3],name='a') var = tf.Variable(tf.random_normal([2, 3], mean=0.0, stddev=1.0)) print('变量张量和常数张量', const, '\n', var) init_op = tf.global_variables_initializer() # 初始化 with tf.Session() as sess: sess.run(init_op) # 程序图结构写入文件 filterWriter = tf.summary.FileWriter('./test', graph=sess.graph) print('变量和张量', sess.run([const, var])) ~~打印结果~~: 图1 <tensorflow.python.framework.ops.Graph object at 0x000002BEBBA1C6A0> 张量a Tensor("Const:0", shape=(), dtype=float32) 图1 <tensorflow.python.framework.ops.Graph object at 0x000002BEBBA1C6A0> op操作sum1 Tensor("Add:0", shape=(), dtype=float32) op重载: Tensor("add_1:0", shape=(), dtype=float32) 图1 <tensorflow.python.framework.ops.Graph object at 0x000002BEBBA1C6A0> 图1 <tensorflow.python.framework.ops.Graph object at 0x000002BEBBA1C6A0> 默认运行图1 [3.0, 6.0, 7.0] 图2 <tensorflow.python.framework.ops.Graph object at 0x000002BEC8135080> placeholder Tensor("Placeholder:0", shape=(?, 3), dtype=float32) Device mapping: no known devices. placeholder运行 [[1. 2. 3.] [4. 5. 6.]] eval a 3.0 eval sum1 7.0 Device mapping: no known devices. Const: (Const): /job:localhost/replica:0/task:0/device:CPU:0 指定运行图2 11.0 指定运行图2 eval c 11.0 Tensor("Placeholder_1:0", shape=(?, 2), dtype=float32) Tensor("Placeholder_1:0", shape=(3, 2), dtype=float32) Tensor("Reshape:0", shape=(2, 3), dtype=float32) WARNING:tensorflow:From C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\framework\op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version. 变量张量和常数张量 Tensor("a:0", shape=(3,), dtype=int32) Instructions for updating: Colocations handled automatically by placer. <tf.Variable 'Variable:0' shape=(2, 3) dtype=float32_ref> 变量和张量 [array([1, 2, 3]), array([[ 1.9696811 , -1.3698837 , -0.863022 ], [ 0.49489492, 0.21399571, 0.9890076 ]], dtype=float32)]
tensorflow的前端系统用来定义程序图的结构,后端系统用来运算图结构
会话 tf.Session() ,使用默认注册的图,只能运行一张图(可以指定运行的图)
会话资源:tf.Variable,tf.QueueBase、tf.ReaderBase,会话结束后需要释放资源
1. sess=tf.Session() sess.run(...):启动 sess.close()
2. with tf.Session() as sess
sess.run()
Session(config=tf.ConfigProto(log_device_placement=True)看到运行设备
3. # 交互式 tf.InteractiveSession()
print('a',a.eval())
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。