python实现
#算法一 调用sklearn里面的方法
# _*_ encoding:utf-8 _*_
from matplotlib import pyplot
import scipy as sp
import numpy as np
from matplotlib import pylab
from sklearn.cross_validation import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import classification_report
from sklearn.linear_model import LogisticRegression
import time
start_time=time.time()
#绘制R/p曲线
def plot_pr(auc_score,precision,recall,label=None):
pylab.figure(num=None, figsize=(6, 5))
pylab.xlim([0.0, 1.0])
pylab.ylim([0.0, 1.0])
pylab.xlabel("Recall")
pylab.ylabel("Precision")
pylab.title("P/R (AUC=%0.2f) / %s" % (auc_score, label))
pylab.fill_between(recall, precision, alpha=0.5)
pylab.grid(True, linestyle="-", color="0.75")
pylab.plot(recall, precision, lw=1)
pylab.show()
#读取
movie_data=sp.load("move_data.npy")
movie_target=sp.load("move_target.npy")
x=movie_data
y=movie_target
#向量空间模型,
count_vec = TfidfVectorizer(binary = False, decode_error = "ignore",\
stop_words = "english")
average = 0
testNum = 10
#注意,训练样本调用fit_transform接口,测试样本调用的是transform接口
for i in range(0,testNum):
#加载数据集,切分数据集80%训练,20%测试
x_train, x_test, y_train, y_test\
= train_test_split(movie_data, movie_target, test_size = 0.2)
x_train = count_vec.fit_transform(x_train)
x_test = count_vec.transform(x_test)
#训练LR分类器
clf=LogisticRegression()
clf.fit(x_train,y_train)
y_pred=clf.predict(x_test)
p=np.mean(y_pred==y_test)
print "第%d次测试的准确率为:%.5f"%(i,p)
average+=p
#精确率与召回率
#answer = clf.predict_proba(x_test)[:,0]#属于第neg类的概率
answer = clf.predict_proba(x_test)[:,1]#属于第pos类的概率
#这个地方可以查看官方文档,
precision, recall, thresholds = precision_recall_curve(y_test, answer)
#thresholds对应着一个向量,个数为answer中不重复的值的个数,每个位置上的值对应着一个threshold,并且是越来越大
#precision 和recall也是一个向量,个数比thresholds多一个,precision最后一个为1,recall最后一个值为0,确保图像从x轴=0开始
#precision每个值对应着,当阈值为thresholds对应位置值的时候的准确度
#例如:当取值取thresholds[0]的时候,precision[0]表示所有的训练集所对应的准确率recall[0]表示召回率
report = answer > 0.5#这里的0.5可以换为其他值
#我们通常使用0.5来划分两类数据,但是我们可以根据P/R图分析,选择一个合适的优秀的阈值。
#print report
print(classification_report(y_test, report, target_names = ["neg", "pos"]))
print("平均精确度为:", average/testNum)
print("花费的时间为:", time.time() - start_time)
plot_pr(0.6, precision, recall, "pos")
实验结果:
第0次测试的准确率为:0.81071
第1次测试的准确率为:0.79643
第2次测试的准确率为:0.79643
第3次测试的准确率为:0.80000
第4次测试的准确率为:0.80714
第5次测试的准确率为:0.81071
第6次测试的准确率为:0.75714
第7次测试的准确率为:0.78214
第8次测试的准确率为:0.78214
第9次测试的准确率为:0.81429
precision recall f1-score support
neg 0.84 0.79 0.81 145
pos 0.79 0.84 0.81 135
avg / total 0.82 0.81 0.81 280
平均精度率为: 0.795714285714
花费时间为: 12.1490001678
通过上图可以看出,如果选择的阈值过低,那么更多的测试样本都将分为1类,因此召回率得到提升,但是要牺牲相应的准确率。 注意precision_recall_curve()方法中的thresholds中的阈值是逐渐增大的,对应到图像是就会,x轴从左到右对应的阈值是逐渐减小的。
# -*- encoding:utf-8 -*-
import matplotlib.pyplot as plt
from matplotlib import animation
import numpy as np
#加载数据集
def loadDataSet():
"""
:return: 输入向量矩阵和输出向量
"""
dataMat=[]
labelMat=[]
fr=open("test.txt","r")#一共有三列,每一列为x1,x2,Y
for line in fr.readlines():
lineArr=line.strip().split("##")
#注意在这里将字符串转换成float型的时候总是遇到问题
#感觉每一行的开头存在其他字符,所以我们多添加了一列"##"分隔符,是的第一个有效数字从第二个开始
dataMat.append([1.0,float(lineArr[1]),float(lineArr[2])])#设x0为1,构成拓展之后的输入向量
labelMat.append(int(lineArr[3]))
return dataMat,labelMat
#可视化数据,画出数据集合逻辑斯蒂最佳回归直线
def plotBestFit(weights):
dataMat,labelMat=loadDataSet()
dataArr=np.array(dataMat)
n=dataArr.shape[0]
x1=[]
y1=[]
x2=[]
y2=[]
for i in range(n):
if int(labelMat[i])==1:
x1.append(dataArr[i,1])
y1.append(dataArr[i,2])
else:
x2.append(dataArr[i,1])
y2.append(dataArr[i,2])
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(x1,y1,s=30,c="red",marker="s")
ax.scatter(x2,y2,s=30,c="green",)
if weights is not None:
x=np.arange(-3.0,3.0,0.1)
y=(-weights[0]-weights[1]*x)/weights[2]# #令w0*x0 + w1*x1 + w2*x2 = 0,其中x0=1,解出x1和x2的关系
ax.plot(x,y)
plt.xlabel("X1")
plt.ylabel("X2")
plt.show()
def sigmoid(inX):
return 1.0/(1+np.exp(-inX))
#逻辑斯提回归梯度上升批量算法,静态展示
def gradAscent_static(dataMatIn,classLabels):
"""
:param dataMatIn: 输入X矩阵,每一行代表一个实例,每一列分别是x0,x1,x2
:param classLabels: 类别标签组成的向量
:return: 权值向量
"""
dataMatrix=np.mat(dataMatIn)#转换为numpy矩阵数据类型,(100,3)
labelMat=np.mat(classLabels).transpose()#转换为numpy矩阵数据类型,(100,1)
m,n=dataMatrix.shape
alpha=0.001
maxCycles=500
weights=np.ones((n,1))#(3,1)
for k in range(maxCycles):
h=sigmoid(dataMatrix*weights)
error=(labelMat-h)#向量减法
weights+=alpha*dataMatrix.transpose()*error#矩阵内积
return weights
def draw_line(weights,lines):
x = np.arange(-5.0, 5.0, 0.1)
y = (-weights[0]-weights[1]*x)/weights[2] #令w0*x0 + w1*x1 + w2*x2 = 0,其中x0=1,解出x1和x2的关系
lines.set_data(x, y)
return lines
def main1():#实现批量梯度上升,展示静态图像
datas,labels=loadDataSet()
weights=gradAscent_static(datas,labels)
plotBestFit(weights)#静态图
if __name__ == "__main__":
main1()
实验结果:
最终得到的权重向量为: [[ 4.12414349]
[ 0.48007329]
[-0.6168482 ]]