文章目录
1 数据集与估计器
不能把拿到的数据全部都用来训练一个模型,因此需要将数据拆分成训练集和测试集
一般75%用于训练,25%用来测试
sklearn.model_selection.train_test_split(*arrays, **options)
x 数据集的特征值
y 数据集的标签值
test_size 测试集的大小,一般为float
random_state 随机数种子,不同的种子会造成不同的随机采样结果。相同的种子采样结果相同。
return 训练集特征值,测试集特征值,训练标签,测试标签(默认随机取)
x_train,y_train,x_test,y_text = sklearn.model_selection.train_test_split(li.data,li.target,test_size = 0.25)
fit_transform():输入数据直接转化
fit():输入data,但不转化,先做数学运算,如标准化中先求平均值、方差
transform():data转化
这里需要注意的是:如果fit和transform的data不一样,则按照fit里的data,因为是根据fit里的data求出的均值和标准差,然后根据transform里的每列进行转化
估计器:
2 分类算法-k近邻算法
根据你的“邻居”来推断出你的类别,需要做标准化处理
定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别
计算距离的公式:
klearn.neighbors.KNeighborsClassifier(n_neighbors=5,algorithm='auto')
n_neighbors:int,可选(默认= 5),k_neighbors查询默认使用的邻居数
algorithm:{‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},可选用于计算最近邻居的算法:‘ball_tree’将会使用 BallTree,‘kd_tree’将使用 KDTree。‘auto’将尝试根据传递给fit方法的值来决定最合适的算法。 (不同实现方式影响效率)
案例:预测入住位置
思路:由于总数据量过大(上千万条数据),可以选取其中一小部分数据来进行预测,就是在10平方公里,挑一小块地方来进行预测。因此要对x,y来进行范围的限制,通过data = data.query(“x > 1.0 & x < 1.25 & y > 2.5 & y < 2.75”)。对于time也要处理成我们熟悉的格式:time_value = pd.to_datetime(data[“time”], unit=‘s’),得到是一个日期格式,因此还要将日期格式转换成字典格式,便于我们后续的操作,time_value = pd.DatetimeIndex(time_value)。转换成字典之后就可以把按照年月日的格式,把里面的值取出来,然后添加到表中去,并且要把以前的time列给删除掉,注意删除列的时候,axis=1!!!
data = pd.read_csv(r"\train.csv")
# 缩小数据范围
data = data.query('x >1.0 & x<1.25 & y>2.5 & y<2.75')
data.info()
#处理时间
time_value = pd.to_datetime(data['time'],unit = 's')
# 构造一些特征
data['day'] = time_val.day
data['hour'] = time_val.hour
data['week'] = time_val.week
# 把time列删除
data = data.drop(['time'],axis = 1)
data.head(10)
# 把签到数量少于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)]
#取出数据当中的特征值和目标值
y = data['place_id']
x = data.drop(['place_id'],axis = 1)
# 进行数据的分割训练集合测试集
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.25)
# 特征工程(标准化)
std = StandardScaler()
# 对测试集和训练集的特征值进行标准化
x_train = std.fit_transform(x_train)
x_test = std.transform(x_test)
# 进行算法流程
knn = KNeighborsClassifier(n_neighbors = 5)
knn.fit(x_train, y_train)
# 预测准确率
print("在测试集上准确率:", knn.score(x_test, y_test))
3 分类模型的评估
1、estimator.score()
一般最常见使用的是准确率,即预测结果正确的百分比
2、混淆矩阵
精确率 = TP / (TP + FP)
召回率 = TP / (TP+FN)
3、F1 score
3.1 评估的API
sklearn.metrics.classification_report(y_true, y_pred, target_names=None)
y_true:真实目标值
y_pred:估计器预测目标值
target_names:目标类别名称
return:每个类别精确率与召回率
4 分类算法-朴素贝叶斯算法
4.1 联合概率和条件概率
联合概率:包含多个条件,且所有条件同时成立的概率
记作:P(A,B) = P(A) * P(B)
条件概率:就是事件A在另外一个事件B已经发生条件下的发生概率记作:P(A|B)
特性:P(A1,A2|B) = P(A1|B)P(A2|B)
注意:此条件概率的成立,是由于A1,A2相互独立的结果
4.2 朴素贝叶斯公式
如对某篇文章进行分类时:
P(科技|文档特征值) = P(科技|词1,词2,词3) = P(词1,词2,词3|科技)*P(科技)/P(词1,词2,词3。。。)
P(科技|文档特征值) = P(金融|词1,词2,词3) = P(词1,词2,词3|科技)*P(金融)/P(词1,词2,词3。。。)
因P(词1,词2,词3。。。)相同,故可忽略。
从上面的例子我们得到娱乐概率为0,这是不合理的,如果词频列表里面有很多出现次数都为0,很可能计算结果都为零,可用拉普拉斯平滑系数解决。
4.3 朴素贝叶斯实现API
sklearn.naive_bayes.MultinomialNB(alpha = 1.0)
朴素贝叶斯分类
alpha:拉普拉斯平滑系数
4.4 案例:分类新闻
朴素贝叶斯进行文本分类
news = fetch_20newsgroups(subset='all')
# 进行数据分割
x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.25)
# 对数据集进行特征抽取
tf = TfidfVectorizer()
# 以训练集当中的词的列表进行每篇文章重要性统计['a','b','c','d']
x_train = tf.fit_transform(x_train)
print(tf.get_feature_names())
x_test = tf.transform(x_test)
# 进行朴素贝叶斯算法的预测
mlt = MultinomialNB(alpha=1.0)
print(x_train.toarray())
mlt.fit(x_train, y_train)
y_predict = mlt.predict(x_test)
print("预测的文章类别为:", y_predict)
# 得出准确率
print("准确率为:", mlt.score(x_test, y_test))
print("每个类别的精确率和召回率:", classification_report(y_test, y_predict, target_names=news.target_names))
4.5 朴素贝叶斯分类优缺点
优点:
1、朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。
2、对缺失数据不太敏感,算法也比较简单,常用于文本分类。
3、分类准确度高,速度快
缺点:
需要知道先验概率P(F1,F2,…|C),因此在某些时候会由于假设的先验
模型的原因导致预测效果不佳。训练集中进行词频统计,若训练集误差大,结果肯定不好。而且朴素贝叶斯估计做了文章中一些词语与其它词语相互独立的假设。
5 模型的选择与调优
5.1 1 交叉验证
为了让被评估的模型更加准确可信
将测试集的数据再分成两份:训练集和验证集
以下图为例:将数据分成5份,其中一份作为验证集。然后经过5次(组)的测试,每次都更换不同的验证集。即得到5组模型的结果,取平均值作为最终结果。又称5折交叉验证。
5.1.2 网格搜索
通常情况下,有很多参数是需要手动指定的(如k-近邻算法中的K值),
这种叫超参数。但是手动过程繁杂,所以需要对模型预设几种超参数组
合。每组超参数都采用交叉验证来进行评估。最后选出最优参数组合建
立模型。
5.1.2.1 API
sklearn.model_selection.GridSearchCV(estimator, param_grid=None,cv=None)
对估计器的指定参数值进行详尽搜索
estimator:估计器对象
param_grid:估计器参数(dict){“n_neighbors”:[1,3,5]}
cv:指定几折交叉验证
fit:输入训练数据
score:准确率
结果分析:
best_score_:在交叉验证中测试的最好结果
best_estimator_:最好的参数模型
cv_results_:每次交叉验证后的测试集准确率结果和训练集准确率结果
5.3 优化KNN算法
# 进行算法流程 # 超参数
knn = KNeighborsClassifier()
# 构造一些参数的值进行搜索
param = {"n_neighbors": [3, 5, 10]}
# 进行网格搜索
gc = GridSearchCV(knn, param_grid=param, cv=2)
gc.fit(x_train, y_train)
# 预测准确率
print("在测试集上准确率:", gc.score(x_test, y_test))
print("在交叉验证当中最好的结果:", gc.best_score_)
print("选择最好的模型是:", gc.best_estimator_)
print("每个超参数每次交叉验证的结果:", gc.cv_results_)
6 决策树与随机森林
6.1 信息论基础
假设有32支球队,猜谁是冠军?每猜一次给一块钱,告诉我是否猜对了,那么我需要掏多少钱才能知道谁是冠军?
把球编上号,从1到32,然后提问:冠 军在1-16号吗?依次询问,只需要五次,就可以知道结果。
因此在不知道任何信息的情况下,各球队是冠军的概率都是1/32,因此此时的信息熵为5,即当这32支球队夺冠的几率相同时,对应的信息熵等于5比特
“谁是世界杯冠军”的信息量应该比5比特少。香农指出,它的准确信息量应该是:
H = -(p1logp1 + p2logp2 + … + p32log32)
H的专业术语称之为信息熵,单位为比特。公式为:
信息熵越大表示信息的不确定性越高。
决策树的划分依据之一—信息增益:
特征A对训练数据集D的信息增益g(D,A),定义为集合D的信息熵H(D)与特征A给定条件下D的信息条件熵H(D|A)之差,即公式为:
信息增益表示得知特征X的信息而使得类Y的信息的不确定性减少的程度
贷款的例子:
H(D):类别中有9个是,6个否
常见的决策树使用的算法:
1、ID3
信息增益 最大的准则
2、C4.5
信息增益比 最大的准则
3、CART
回归树: 平方误差 最小
分类树: 基尼系数 最小的准则 在sklearn中默认的划分的原则
6.2 API
class sklearn.tree.DecisionTreeClassifier(criterion=’gini’, max_depth=None,random_state=None)
决策树分类器
criterion:默认是’gini’系数,也可以选择信息增益的熵’entropy’
max_depth:树的深度大小
random_state:随机数种子
method:
decision_path:返回决策树的路径
6.3 泰坦尼克号乘客生存分类案例
# 获取数据
titan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")
# 处理数据,找出特征值和目标值
x = titan[['pclass', 'age', 'sex']]
y = titan['survived']
# 缺失值处理
x['age'].fillna(x['age'].mean(), inplace=True)
# 分割数据集到训练集合测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
# 进行处理(特征工程)特征-》类别-》one_hot编码
dict = DictVectorizer(sparse=False)
x_train = dict.fit_transform(x_train.to_dict(orient="records"))
print(dict.get_feature_names())
x_test = dict.transform(x_test.to_dict(orient="records"))
# 用决策树进行预测
dec = DecisionTreeClassifier()
dec.fit(x_train, y_train)
# 预测准确率
print("预测的准确率:", dec.score(x_test, y_test))
# 导出决策树的结构
export_graphviz(dec, out_file="./tree.dot", feature_names=['年龄', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', '女性', '男性'])
注意点:
1、进行处理(特征工程)特征-》类别-》one_hot编码
dict = DictVectorizer(sparse=False)
x_train = dict.fit_transform(x_train.to_dict(orient=“records”))
print(dict.get_feature_names())
x_test = dict.transform(x_test.to_dict(orient=“records”))
根据对之前部分trainData进行fit的整体指标,对剩余的数据(testData)使用同样的均值、方差、最大最小值等指标进行转换transform(testData),从而保证train、test处理方式相同。所以,一般都是这么用的
2、
sklearn.tree.export_graphviz() 该函数能够导出DOT格式
tree.export_graphviz(estimator,out_file='tree.dot’,feature_names=[‘’,’’])
3、
x_train.to_dict(orient=“records”) 是把x_train转化成字典,orient =‘records’’表示转化后是 list形式:[{column(列名) : value(值)}……{column:value}]
6.5 决策树的优缺点及改进
优点:
1、简单的理解和解释,树木可视化。
2、需要很少的数据准备,其他技术通常需要数据归一化
缺点:
1、存在过拟合问题
2、决策树可能不稳定,因为数据的小变化可能会导致完全不同的树
被生成
改进:
1、减枝cart算法,把图中value小于某个值的枝桠剪掉
2、随机森林
6.4 随机森林
6.1 什么是随机森林
随机森林属于集成学习,集成学习通过建立几个模型组合的来解决单一预测问题。它的工作原理是生成多个分类器/模型,各自独立地学习和作出预测。这些预测最后结合成单预测,因此优于任何一个单分类的做出预测。
在机器学习中,随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定
随机森林建立多个决策树的过程:
假设这个数据集有N个样本,M个特征
1、单个树建立过程:
随机在N个样本中选择一个样本,重复N次,样本可能重复
随机在M个特征中选出m个特征
2、建立10棵决策树
为什么要随机抽样训练集?
如果不进行随机抽样,每棵树的训练集都一样,那么最终训练出的树分类结果也是完全一样的
为什么要有放回地抽样?
如果不是有放回的抽样,那么每棵树的训练样本都是不同的,都是没有交集的,这样每棵树都是“有偏的”,都是绝对“片面的”(当然这样说可能不对),也就是说每棵树训练出来都是有很大的差异的;而随机森林最后分类取决于多棵树(弱分类器)的投票表决。
6.2 随机森林API
6.3 优势
- 在当前所有算法中,具有极好的准确率
- 能够有效地运行在大数据集上
- 能够处理具有高维特征的输入样本,而且不需要降维
- 能够评估各个特征在分类问题上的重要性
- 对于缺省值问题也能够获得很好得结果
6.4 泰坦尼克号乘客生存分类分析
# 随机森林进行预测 (超参数调优)
rf = RandomForestClassifier()
param = {"n_estimators": [120, 200, 300, 500, 800, 1200], "max_depth": [5, 8, 15, 25, 30]}
# 网格搜索与交叉验证
gc = GridSearchCV(rf, param_grid=param, cv=2)
gc.fit(x_train, y_train)
print("准确率:", gc.score(x_test, y_test))
print("查看选择的参数模型:", gc.best_params_)