前言
提及人工智能、机器学习、深度学习、算法工程师,可能普通人会下意识地联想到高数、线性代数、概率论数理统计、统计学习方法这些复杂的算法,而机器学习算法的本质也确实是一些数学中的统计方法。
作为1个终生学习者,我们不能因为没有数学基础,望而却步,错失了从当下火热的人工智能浪潮中分一杯羹的大好机会。
大部分机器学习算法设计和实现都是由世界一流的算法工程师(非市面上的那些算法工程师)设计并实现的,而绝大一大部分人都只是在调用这些已经封装好的算法并调参和优化自己的模型;
- 数据集收集
- 数据集清洗
- 特征工程
- 反复训练、预测、评估、调参数、优化得出最优的模型
- 把训练好的模型应用到线上
在开始学习机器学习之前,一定要明确机器学习和之前编程思维的异同之处!
机器学习跟普通程序最大的不同是,通常程序是在给定输入数据的情况下,通过告诉计算机处理数据的规则,然后得到处理后的结果。
简而言之就是像人类一样,使机器经过学习之后,也具备对未知事物的判断和决策能力。
而机器学习的流程是让机器来从已知的历史数据中学习到决策规则,得出模型,让模型去预测未来的未知数据。
如果你之前Pandas玩地比较溜,也可以借助Python强大的数据分析和机器学习库,例如numpy、Pandas、Sklearn (包含了常见的主流算法)站到巨人的肩膀上,从而人工智能时代中分一份羹。
人工智能就是让机器模拟人类的学习过程,从未产生人类的智慧。
机器学习是人工智能的一种实现途径;
传统的预测-----》店铺销量预测、量化交易
图像识别-------》自动驾驶
说白了就是所有人类智慧能决策的问题,都尝试让机器去解决。
什么是机器学习?
例1
如何让机器去识别猫还是狗?
从数据中(大量的猫、狗的图片)中自动分析获得模型(辨别猫和狗的规律),从而使机器拥有能够识别毛和狗的的能力。
例2
如何让机器分析一下北京未来20年的房价走势。
从历史数据中,自动分析获得模型,从而让机器拥有预测房屋价格的能力。
一、数据集
机器学习需要从历史数据中进行自动分析得出模型,这些机器学习需要的历史数据就叫数据集。
数据集的结构?
数据集结构=特征值+目标值
特征值就是:一个由数字组成二维数组也就是数学中的矩阵。
[ [5.1 3.5 1.4 0.2] [4.9 3. 1.4 0.2] [4.7 3.2 1.3 0.2] [4.6 3.1 1.5 0.2] [5. 3.6 1.4 0.2] [5.4 3.9 1.7 0.4] [4.6 3.4 1.4 0.3] [5. 3.4 1.5 0.2] ]
目标值通常为类别也就是答案
from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split # #数据集 #数据集的数据类型,是1个继承自字典的bunch类型。 iris_data_sets = load_iris() # print("鸢尾花数据集:\n",iris_data_sets) # print("查看数据集描述:\n",iris_data_sets["DESCR"]) # print("查看特征值的名称:\n",iris_data_sets.feature_names) # print("查看特征值:\n",iris_data_sets.data) # print("查看目标值的名称:\n",iris_data_sets.target_names)
数据集划分
当我们拿到数据集之后,是否要全部用于训练1个模型呢?我们需要留出20%-30%的数据进行测试。
机器学习一般的数据集会划分为2个部分:
训练数据集:用于训练、构建模型
测试数据集:在模型构建完成之后,用于检验、评估模型是否有效?
训练集:70% 80% 75%
from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split #数据集的数据类型,是1个继承自字典的bunch类型。 iris_data_sets = load_iris() # 数据集的划分 x_train, x_test, y_train, y_test = train_test_split(iris_data_sets.data, iris_data_sets.target, test_size=0.3) print(x_train.shape) print(y_test.shape)
二、特征工程
特征工程是使用专业背景知识和技巧处理数据,使得特征能在机器学习算法上发挥更好的作用和过程。
特征工程会使算法得到最好的发挥,最终直接影响机器学习预测效果。
我们使用
pandas对数据进行数据处理、清洗
sklearn对数据做特征工程
特征工程:包含特征抽取、特征预处理、特征降维这3个部分。
1.特征抽取/提取 feature_extraction
机器学习就是50年代一些搞统计的人,想出来的机器学习实现途径,而机器学习算法就是一些统计方法,而统计方法就是一个又一个的数学公式。
数学公式是无法处理字符串的,这就是我们在特征提取阶段考虑的事情,就是如何把文本类型转换成数值。
特征提取:就是将任意数据(如文本和图形)转换为可用于机器学习的数字特征。
我们使用sklearn中的sklearn.feature_extraction对不同的数据进行不同的特征值化;
1.1.字典特征提取
from sklearn.feature_extraction import DictVectorizer data = [ {"city": "北京", "temperature": 100}, {"city": "上海", "temperature": 60}, {"city": "深圳", "temperature": 30}, ] #1.实例化1个转换器类 transfer=DictVectorizer() #2.调用1个fit_transform() data_new=transfer.fit_transform(data) print(data_new) print(transfer.get_feature_names()) """ [ [ 0. 1. 0. 100.] [ 1. 0. 0. 60.] [ 0. 0. 1. 30.] ] 如果我们使用one-hot表示1000中类别,每行就会出现999个0。 使用稀疏矩阵(sparse matrix):将非0只按坐标位置表示出来,这种机制可以节省内存,提高加载效率。 (0, 1) 1.0 (0, 1)代表:第0行的第1列 (0, 3) 100.0 (0, 3)代表:第0行的第3列 (1, 0) 1.0 (1, 0)代表:第1行的第0列 (1, 3) 60.0 (2, 2) 1.0 (2, 3) 30.0 """
1.2.文本特征提取
A.统计单词出现的次数CountVectorizer
from sklearn.feature_extraction.text import CountVectorizer #我可以使用CountVectorizer对文本单词出现的频率进行处理 data=[ "life is short, i like python", "life is too long, i dislike python" ] #1.实例化1个转换器类 transfer=CountVectorizer(stop_words=["i"]) #2.调用1个fit_transform() data_new=transfer.fit_transform(data) print(transfer.get_feature_names()) print(data_new.toarray())
由于中文没有空格隔开的特性,我们就需要借助jiaba进行分词。
import jieba from sklearn.feature_extraction.text import CountVectorizer data = [ "我爱北京天安门,天安门上太阳升", "我爱你你却爱着他爸爸", "我爱你你妹妹却爱着我" ] data_new = [] for sentense in data: text = " ".join(list(jieba.cut(sentence=sentense))) data_new.append(text) # print(jieba.cut(data))#返回1个词语生成器 transfer = CountVectorizer() data_final = transfer.fit_transform(data_new) print(transfer.get_feature_names()) print(data_final.toarray())
B.Tfidf关键词
TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中出现很少、
则认为此词或短语具有很好的类别区分能力,适合用来分类。
import jieba from sklearn.feature_extraction.text import TfidfVectorizer data = [ "李自成(1606年9月22日—1645年5月17日),原名鸿基,小字黄来儿,又字枣儿, [1] 明末农民起义领袖,世居陕西榆林米脂李继迁寨。", "童年时给地主牧羊,曾为银川驿卒。", "崇祯二年(1629年)起义,后为闯王高迎祥部下的闯将,勇猛有识略。荥阳大会时,提出“分兵定向、四路攻战”的方案,受到各部首领的赞同。", ] def cut_words(data): data_new = [] for sent in data: text = " ".join(list(jieba.cut(sentence=sent))) data_new.append(text) return data_new transfer = TfidfVectorizer() final_data = transfer.fit_transform(cut_words(data)) # print(transfer.get_feature_names()) for i in range(0, len(final_data.toarray()[0])): print(transfer.get_feature_names()[i], "<------->", final_data.toarray()[0][i])
1.3.图形特征提取(深度学习)
2.特征预处理 preprocing
特征的单位或者大小相差较大,或者某个特征的方差比其他特征要大出很多,这个较大的特征就很容易支配模型的预测结果。
使算法无法学习到其他特征信息。
当我们从任意数据中提取到了数字特征之后,就需要对这些数字特征进行无量纲化。
我们使用无量纲化的目的主要是把不同规格的数据,转换到同一规格。
我们可以在Sklearn.preprocing的API中找到数据无量纲化的工具。
2.1归一化
归一化就是将原始的数据进行变换,把数据映射到一个区间(默认[0,1])内。
from sklearn.preprocessing import MinMaxScaler import pandas as pd #1.获取数据 df=pd.read_csv("dating.csv") df=df.iloc[:,:3] #实例化1个转换器类 transfer=MinMaxScaler(feature_range=[2,3]) #调用fit_transform new_df=transfer.fit_transform(df) print(new_df)
2.2标准化
由于归一化时使用的公式中使用了最大值和最小值, 如果出现异常值,也会影响计算结果。
标准化就是对原始数值特征变换成均值为0,标准差为1的范围内。
from sklearn.preprocessing import StandardScaler import pandas as pd #读取数据 data=pd.read_csv("dating.csv") #实例化转换器 transfer=StandardScaler() #调用转换器的fit_transform() new_data=transfer.fit_transform(data) print(new_data)
3.特征降维
我们知道特征就是1个二维数组。
[ [0.33193158, 0.41660188, 0.24523407, 1.24115502], [-0.87247784, 0.13992897, 1.69385734, 0.01834219], [-0.34554872, -1.20667094, -0.05422437, -1.20447], [-0.32171752, 0.96431572, 0.06952649, 1.24115502], [0.65959911, 0.60699509, -0.20931587, 1.24115502], [0.46120328, 0.31183342, 1.00680598, 1.24115502], ]
在模型训练的时候,算法根据特征进行学习。如果特征本身存在问题或者特征之间相关性较强,对于算法学习预测会影响很大。
降维就是针对这个特征二维数组,减少特征的列数, 缩减数据集中的冗余特征,减少特征的个数。得到一组不相关的特征。
3.1特征选择 feature_selection
3.1.1Filter过滤式
A.方差选择法
我们过滤掉方差比较低的特征就可以达到特征过滤的效果。
#过滤低方差特征 import pandas as pd from sklearn.feature_selection import VarianceThreshold #读取数据 data=pd.read_csv("factor_returns.csv") data=data.iloc[:,1:-2] #实例化1个转换器类 transfer=VarianceThreshold(threshold=10) data_new=transfer.fit_transform(data) print(data_new.shape)
B.相关系数法
衡量特征和特征之间的相关程度
使用皮尔森计算2列之间的相关系数
import pandas as pd from sklearn.feature_selection import VarianceThreshold from scipy.stats import pearsonr #读取数据 data=pd.read_csv("factor_returns.csv") #计算某两个变量之间的相关系数 r=pearsonr(data["pe_ratio"],data["pb_ratio"]) print(r[0])
3.1.2Embeded嵌入式
A.决策树
B.正则化
C.深度学习
3.2主成分分析 decomposition
特征选择就是当多个特征列之间存在较强的相关性,根据特征列之间的相关系数,筛选出其中1个作为适合的特征值。
而主成分分析是一种方法,可以自动把相关性较强的N列进行合并压缩,最终形成1个新的特征列。
主成分分析(PCA)也是一种数据维度压缩手段,例如我们可以把一个二维数组简化为一维,并且在保证损失少量信息的情况下。
from sklearn.decomposition import PCA # PCA降维 data = [ [2, 8, 4, 5], [6, 3, 0, 8], [5, 4, 9, 1], ] # 1.实例化1个转换器类 transfer = PCA(n_components=3) # 把4个特征压缩成3个特征 new_data = transfer.fit_transform(data) print(new_data) transfer = PCA(n_components=0.95) # 保留95%的原有特征信息 # 调用1个fit_transform new_data = transfer.fit_transform(data) print(new_data)
Instacart降维案例分析
import pandas as pd from sklearn.decomposition import PCA order_products = pd.read_csv("./instacart/order_products__prior.csv") products = pd.read_csv("./instacart/products.csv") orders = pd.read_csv("./instacart/orders.csv") aisles = pd.read_csv("./instacart/aisles.csv") tab1 = pd.merge(aisles, products, on=["aisle_id", "aisle_id"]) tab2 = pd.merge(tab1, order_products, on=["product_id", "product_id"]) tab3 = pd.merge(tab2, orders, on=["order_id", "order_id"]) table=pd.crosstab(tab3["user_id"],tab3["aisle"]) data=table[:1000] transfer=PCA(n_components=0.95) new_data=transfer.fit_transform(data) print(new_data.shape)
机器学习算法的分类
数据集由特征值和目标值构成,我们根据数据集的结构选择要使用的算法;
根据数据集中是否包含目标值,我们可以选择监督学习算法和无监督学习算法。
根据数据集中目标值的类型,我们可以选择分类算法(类别)和回归算法(连续性数值)。
监督学习(Supervised Learning):
1.分类问题:如果目标值为类别(离散)的时,我们面临的就是分类问题;如例1
2.回归问题: 如果目标值为连续数据(连续)的时,我们面临的就是回归问题;如例2
从成对的输入/输出中,进行学习的机器学习算法叫做监督学习算法(Supervised Larning Algorithm);
分类算法有:K-近邻算法、贝叶斯分类、决策树、随机森林、逻辑回归、线性回归、岭回归。
无监督学习(Unsupervised Learing)
当我们的数据集结构中不包含目标值的时候,也就是只有输出,没有输出,没有目标值对算法进行监督那就是无监督学习方法。
在无监督学习过程中,只有输入是已知的,数据集没有为算法提供输出数据。那么理解和评估这些无监督学习算法(Unsupervised Learing Algorithm)往往也会更加困难。
无监督的学习的算法有:聚类 K-means
应用场景
- 预测明天气温是多少度? 回归
- 预测明天是晴天还是阴天?分类
- 人脸年龄预测?回归/分类
- 人脸识别?分类
- 在软件造价过程中,从开发需求文档中识别出ILF/EIF/IE/EOEQ?分类
机器学习开发流程
- 获取数据
- 处理数据
- 特征工程(转换成机器学习算法可以识别的数据。Pands
- 选择适合的算法,也就是分类器classifer()
- 使用训练集进行训练 fit(train_x, train_y)得出模型文件
- 使用测试集对模型效果进行评估evaluate(test_x, test_y),如果评估效果不好继续循环
- 应用模型:知道验证模型效果较好,就用新数据进行结果预测predict(x,y)
市面上的算法工程师:基本都在做特征工程也就是做数据清晰、处理、把机器学习模块集成到公司产品中,机器学习里面使用的算法,都是世界上一流算法工程师写好的!
所以让我们大胆地去尝试使用机器学习库和已经设计好的算法,结合上自己的数据去做机器学习吧;
转换器和评估器
转换器 Transformer
在Sklearn中所有的转换器类都继承至Transformer基类, 转换器是特征工程的接口, 作用是帮助我们做特征工程,比如特征值提取、标准化和特征降维。
转换器都有1个fit_transform()方法。
fit_transform是由fit和transform这2个方法封装而成。其中fit()的作用是计算公式需要的相关系数,而transform()是把计算出来的系数带入数学公式进行最终转换。
我们以标准化为例:
标准化的公式为(x-men)/std,那么fit()就会先计算每一列的平均值和标准差,而tranform()把计算好的平均值和标准差带入公式进行特征的标准化。
估计器 Estimator
Sklearn中所有机器学习算法都继承至Estimator类。
1.用于分类问题的预估器
- sklearn.neighbors K-近邻算法
- sklearn.naive_bayes 贝叶斯算法
- sklearn.linear_model 逻辑回归算法
- sklearn.tree 决策树和随机森林
2.用于回归问题的预估器
- sklearn.linear_model.LinearRegression 线性回归
- sklearn.linear_model.Ridge 岭回归
3.用于无监督学习的预估器
- sklearn.cluster.Kmeans 聚类
4.估计器工程流程
- 实例化1个Estimator类
- estimator.fit(x_train,y_train)训练完毕之后,模型生成。
- y_predict=estimator.predict(x_test) 预测
- y_test==y_predict 或者 accuracy=estimator.score(x_test,y_test) 验证模型
分类算法
我们可以根据数据集是否包含目标值,来使用监督学习和无监督学习算法。
我们根据目标值的类型,判断是分类问题还是回归问题,决定使用分类算法和回归算法。
1.KNN算法
KNN算法的核心思想是根据你的邻居判断你的类别
knn属于分类算法的一种,其核心思想是根据邻居的类别判断自身的类型。
# 用KNN算法对鸢尾花进行分类 from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import StandardScaler # 1.获取数据 iris = load_iris() """ attribute infromation 萼片长度(厘米) 萼片宽度(厘米) 花瓣长度(厘米) 花瓣宽度(厘米) speal_length, speal_width, petal_length, petal_width [ [5.1 3.5 1.4 0.2] [4.9 3. 1.4 0.2] [4.7 3.2 1.3 0.2] [6.2 3.4 5.4 2.3] ] ---------------------------------------------- class 0:山鸢尾 1变色鸢尾 2维吉尼亚鸢尾 [0,1,2,3] """ # print(iris.data) # print(iris.target) # 2.划分数据集 x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22) # 3.特征工程:标准化 transfer = StandardScaler() x_train = transfer.fit_transform(x_train) # 测试集继续使用训练集中fit出来的平均值和标准差,对测试集的数据进行标准化。 x_test = transfer.transform(x_test) # 4.KNN算法预估器 estimator = KNeighborsClassifier(n_neighbors=3) estimator.fit(x_train, y_train) # 5.模型评估 # 方法1:手动对比真实值和预测出来的值 y_predict = estimator.predict(x_test) print(y_test == y_predict) # 方法2:自动计算准确率 accuracy = estimator.score(x_test, y_test) print(accuracy)
--------------------
import pandas as pd from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import GridSearchCV # 获取数据 data_df = pd.read_csv("./train.csv") #转换时间戳成日、周、时 time_value = pd.to_datetime(data_df["time"], unit="s") date_value = pd.DatetimeIndex(time_value) data_df["day"],data_df["weekday"],data_df["hour"]=date_value.day,date_value.weekday,date_value.hour #过滤掉签到次数少的地点 place_count=data_df.groupby("place_id").count()["row_id"] #过滤至少出现2次以上的地点的place_id left_data=place_count[place_count>=2].index.values data_df=data_df[data_df["place_id"].isin(left_data)] #特征工程 x_train, x_test, y_train, y_test = train_test_split(data_df[["x","y","accuracy","day","weekday","hour"]],data_df["place_id"], test_size=0.5,random_state=5) tranfer=StandardScaler() x_train=tranfer.fit_transform(x_train) x_test=tranfer.transform(x_test) #训练模型 estimator=KNeighborsClassifier() param_dict={"n_neighbors":[3,2]} estimator=GridSearchCV(estimator,param_grid=param_dict,cv=2) estimator.fit(x_train,y_train) #预测模型 accuracy = estimator.score(x_test, y_test) print("准确率\n",accuracy) y_predict = estimator.predict(x_test) print(y_test == y_predict) print("最佳参数\n",estimator.best_params_) print("最佳结果\n",estimator.best_score_) print("最佳估计器\n",estimator.best_estimator_) print("交叉验证结果\n",estimator.cv_results_)
2.朴素贝叶斯算法
1.什么是朴素贝叶斯分类方法?
P=Possibility=概率
W=Words=特征值
C=Category=类别=目标值
朴素贝叶斯算法是把每一个样本(Row)的特征值和所有类别(目标值),都带入1个贝叶斯公式,算出的哪组概率高?预测值就属于哪个!
朴素贝叶斯=朴素+贝叶斯,朴素是假设特征和特征之间是相互独立的,贝叶斯是1个贝叶斯公式。
当概率为0时,我就需要给每个类别设置1个拉普拉斯平滑系数也就是Sklearn中的alpha参数。
sklearn.naive_bayes import MultinomialNB(alpha=1)
2.使用朴素贝叶斯对新闻进行分类
from sklearn.datasets import fetch_20newsgroups from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.model_selection import train_test_split from sklearn.naive_bayes import MultinomialNB # 1.获取数据 news_data = fetch_20newsgroups(subset="all") # 2.划分数据集 x_train, x_test, y_train, y_test = train_test_split(news_data.data, news_data.target) # 3.特征工程 transfer = TfidfVectorizer() # 3.1文本特征抽取 x_train = transfer.fit_transform(x_train, y_train) x_test = transfer.transform(x_test, y_test) # 4.朴素贝叶斯预估器流程 estimator = MultinomialNB() estimator.fit(x_train, y_train) y_predict = estimator.predict(x_test) # 5.模型评估 # 方法1:直接对比真实值和预测值 print("直接对比真实值和预测值\n", y_test == y_predict) # 方法2:计算准确率 score = estimator.score(x_test, y_test) print("准确率为:\n", score)
3.决策树算法
3.1.认识决策树
决策树的思想来源非常朴素,其实就是if-else这种逻辑判断结构。
决策树的核心思想就是帮助我们在一堆特征中,找到特征的优先顺序,并比较其优先级大小进行排序,从而形成1棵可以最快做出决策的决策树。
3.2.决策树分类的依据之一------信息增益
我们需要找到1种数学的方法,帮助我们对一堆特征进行排序,得出我们应该先看哪一个特征、再看哪一个特征、最后再看哪一特征,从而最快速的得出问题的结论。
3.2.1.什么是信息?
在信息论中信息是指,可以消除随机不确定性东西。来看下面一段对话:
小明:我今年22岁。 --------->信息:这句话消除了我对小明年龄的随机不确定性。
小刚:小明明年23岁。 --------->不是信(废话):小明已经告诉我她22岁了。
3.2.2.如何计算信息熵?
信息熵:就是信息不确定性的大小是多少?
3.2.3.如何计算条件熵?
3.2.4.如何计算信息增益?
当我们知道某1个特征之后,信息熵(训练集的总不确定性)的减少程度就是条件熵。
信息熵-条件熵=信息增益。
信息增益最大的特征,应该作为决策树的根,进行优先考虑。
当然决策树的划分原理不止信息增益这一种,还有其他方法,但是其原理都大同小异。
- ID3:信息增益最大准则
- C4.5:信息增益比 最大准则
- CART:
- 分类树:基尼(jini)系数最小准则,在sklearn中可以选择划分的默认原则
- 优势:划分更加细致
3.3.sklearn决策树API
from sklearn.tree import DecisionTreeClassifier DecisionTreeClassifier(criterion="gini",max_depth=3,random_state=8) ''' criterion:默认为gini系数,也可以选择信息增益的熵 entropy max_depth:树的深度过深会和训练集拟合程度太高,影响模型的泛化能力。 random_state:随机数种子 '''
决策树对鸢尾花进行分类
from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier # 1.获取数据集 iris_data_sets = load_iris() # 2.划分数据集 x_train, x_test, y_train, y_test = train_test_split(iris_data_sets.data, iris_data_sets.target, random_state=22) # 3.决策树预估器 estimator = DecisionTreeClassifier(criterion="entropy") estimator.fit(x_train, y_train) y_predict = estimator.predict(x_test) print("直接对比真实值和预测值\n", y_predict == y_test) score = estimator.score(x_test, y_test) print("准确率为\n", score)
4.随机森林
4.1什么是集成学习方法?
集成学习方法就是组合N个模型来解决1个问题。
集成学习方法的工作流程是生成多个分类器(模型),让每1个分类器(模型)各自单独地进行训练+预测。
而最终的预测结果就是获取多个分类器(模型)预测结果的1个众数,少数服从多数。
其核心思想就是3个臭皮匠合成1个诸葛亮。
4.2什么是随机森林?
在机器学习中,随机森林就是随机生成1个包含N个决策树的分类器,随机森林的预测结果由森林中所有决策树输出结果的众数来决定。
例如:随机森林中训练了5棵树,其中有4棵决策树的预测结果是True,1棵决策树的预测结果为Flase,那么最终的投票结果就是True.
4.3随机森林的原理过程?
那这个5棵决策树是怎么随机生成的呢?随机就保证了5棵决策树的独立性。
训练集随机:
训练集是使用Bootstrap(随机有放回的抽样)方法随机出来的。
特征值随机:
从训练集的M个特征之中,随机抽取m个特征。并且M远远大于m。
这样做的好处就是可以对特征进行降维度、加速计算过程,由于真理掌握在少数人的手中,这样做的好处也会让重要的特征脱颖而出。
4.4 Sklearn API
#n_estimators: 随机森林中决策树的数量 #criteria:default=gini,划分决策树决策的划分依据 #max_depth:决策树的最大深度 #max_features:每个决策树获取的最大特征值个数 #bootstrap:是否在构建决策树时使用放回抽样 from sklearn.ensemble import RandomForestClassifier estimator=RandomForestClassifier()
4.5随机森林预测案例
随机森林算法不求特征之间的距离,所以不需要进行标准化。
如果特征值属于类别,可以把这些类别转换成One-hot编码。
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.feature_extraction import DictVectorizer from sklearn.model_selection import GridSearchCV from sklearn.ensemble import RandomForestClassifier # 1.获取数据 titanic_df = pd.read_csv("./titanic.csv") # 筛选特征值+目标值 titanic_df = titanic_df[["pclass", "age", "sex", "survived"]] # 填充age列缺失值 titanic_df.iloc[:, 1].fillna(titanic_df.iloc[:, 1].mean(), inplace=True) #划分特征值和目标值 x_titanic=titanic_df.iloc[:,0:3] y_titanic=titanic_df.iloc[:,3] #转换数据集为字典,进行One-hot编码。 titanic_dict=x_titanic.to_dict(orient="records") #划分数据集 x_train,x_test,y_train,y_test=train_test_split(titanic_dict,y_titanic,random_state=22) #抽取字典的数字特征 transfer=DictVectorizer() x_train=transfer.fit_transform(x_train) x_test=transfer.transform(x_test) #预估器 estimator=RandomForestClassifier(n_estimators=20,max_depth=8,bootstrap=True) # #网格搜索,进行调参 # param_dict={"n_estimators":[120,200,300,500,800,1100],"max_depth":[5,8,15,25,30]} # estimator=GridSearchCV(estimator,param_grid=param_dict,cv=3) estimator.fit(x_train,y_train) y_predict=estimator.predict(x_test) print(y_test==y_predict) score=estimator.score(x_test,y_test) print(score)
-----------------------
网格搜索版本
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.feature_extraction import DictVectorizer from sklearn.model_selection import GridSearchCV from sklearn.ensemble import RandomForestClassifier # 1.获取数据 titanic_df = pd.read_csv("./titanic.csv") # 筛选特征值+目标值 titanic_df = titanic_df[["pclass", "age", "sex", "survived"]] # 填充age列缺失值 titanic_df.iloc[:, 1].fillna(titanic_df.iloc[:, 1].mean(), inplace=True) #划分特征值和目标值 x_titanic=titanic_df.iloc[:,0:3] y_titanic=titanic_df.iloc[:,3] #转换数据集为字典,进行One-hot编码。 titanic_dict=x_titanic.to_dict(orient="records") #划分数据集 x_train,x_test,y_train,y_test=train_test_split(titanic_dict,y_titanic,random_state=22) #抽取字典的数字特征 transfer=DictVectorizer() x_train=transfer.fit_transform(x_train) x_test=transfer.transform(x_test) #预估器 estimator=RandomForestClassifier(bootstrap=True) #网格搜索,进行调参 param_dict={"n_estimators":[120,200,300,500,800,1100],"max_depth":[5,8,15,25,30]} estimator=GridSearchCV(estimator,param_grid=param_dict,cv=3) estimator.fit(x_train,y_train) score=estimator.score(x_test,y_test) print(score) print('最佳参数\n',estimator.best_params_) print('最佳结果\n',estimator.best_score_) print('最佳预估器\n',estimator.best_estimator_) print('交叉验证结果\n',estimator.cv_results_)
---------------------
最佳参数 {'max_depth': 5, 'n_estimators': 120} 最佳结果 0.8384146341463414 最佳预估器 RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None, criterion='gini', max_depth=5, max_features='auto', max_leaf_nodes=None, max_samples=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, n_estimators=120, n_jobs=None, oob_score=False, random_state=None, verbose=0, warm_start=False) 交叉验证结果 {'mean_fit_time': array([0.18966651, 0.32133325, 0.46866663, 0.77900004, 1.30966671, 2.216 , 0.23800008, 0.40200011, 0.60300001, 0.98866669, 1.65633345, 2.24066679, 0.26066661, 0.41766667, 0.61899996, 1.03799987, 1.72966655, 2.3670001 , 0.261 , 0.44833326, 0.64533337, 1.09066669, 1.72366667, 2.35166677, 0.25266655, 0.60433332, 0.70866656, 1.13833332, 1.66466665, 2.28666671]), 'std_fit_time': array([0.00329979, 0.00478418, 0.00339936, 0.01267549, 0.07995978, 0.33793184, 0.00535403, 0.00748337, 0.03043034, 0.01667986, 0.05402056, 0.09628203, 0.02072576, 0.00895671, 0.01639105, 0.00454612, 0.03479785, 0.04752541, 0.00432055, 0.0055577 , 0.01465913, 0.01307248, 0.01189754, 0.10669078, 0.00377124, 0.1353817 , 0.02088576, 0.01291863, 0.02242525, 0.0572499 ]), 'mean_score_time': array([0.0146668 , 0.02166677, 0.03266676, 0.05499991, 0.11766664, 0.13266667, 0.01566664, 0.02599994, 0.03766664, 0.06266665, 0.10199992, 0.13733331, 0.01800005, 0.02900012, 0.03766664, 0.06566683, 0.10366662, 0.16000001, 0.01666665, 0.02799996, 0.03933326, 0.06699999, 0.10466663, 0.13966656, 0.01766682, 0.03233345, 0.04066666, 0.06833339, 0.13166658, 0.14133334]), 'std_score_time': array([4.71370354e-04, 4.71538951e-04, 9.42853099e-04, 8.16534738e-04, 4.55068142e-02, 2.49436366e-03, 4.71314168e-04, 8.16534738e-04, 4.71257962e-04, 4.71370354e-04, 6.37696629e-03, 2.62470110e-03, 1.12391596e-07, 1.63306948e-03, 4.71257962e-04, 9.42796908e-04, 2.86752032e-03, 9.93310975e-03, 1.69973701e-03, 1.41416726e-03, 1.88553761e-03, 8.16437410e-04, 4.71314168e-04, 4.49697539e-03, 4.71370354e-04, 5.79278521e-03, 2.49442739e-03, 2.49444862e-03, 2.68368817e-02, 3.09116208e-03]), 'param_max_depth': masked_array(data=[5, 5, 5, 5, 5, 5, 8, 8, 8, 8, 8, 8, 15, 15, 15, 15, 15, 15, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30, 30, 30], mask=[False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False], fill_value='?', dtype=object), 'param_n_estimators': masked_array(data=[120, 200, 300, 500, 800, 1100, 120, 200, 300, 500, 800, 1100, 120, 200, 300, 500, 800, 1100, 120, 200, 300, 500, 800, 1100, 120, 200, 300, 500, 800, 1100], mask=[False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False], fill_value='?', dtype=object), 'params': [{'max_depth': 5, 'n_estimators': 120}, {'max_depth': 5, 'n_estimators': 200}, {'max_depth': 5, 'n_estimators': 300}, {'max_depth': 5, 'n_estimators': 500}, {'max_depth': 5, 'n_estimators': 800}, {'max_depth': 5, 'n_estimators': 1100}, {'max_depth': 8, 'n_estimators': 120}, {'max_depth': 8, 'n_estimators': 200}, {'max_depth': 8, 'n_estimators': 300}, {'max_depth': 8, 'n_estimators': 500}, {'max_depth': 8, 'n_estimators': 800}, {'max_depth': 8, 'n_estimators': 1100}, {'max_depth': 15, 'n_estimators': 120}, {'max_depth': 15, 'n_estimators': 200}, {'max_depth': 15, 'n_estimators': 300}, {'max_depth': 15, 'n_estimators': 500}, {'max_depth': 15, 'n_estimators': 800}, {'max_depth': 15, 'n_estimators': 1100}, {'max_depth': 25, 'n_estimators': 120}, {'max_depth': 25, 'n_estimators': 200}, {'max_depth': 25, 'n_estimators': 300}, {'max_depth': 25, 'n_estimators': 500}, {'max_depth': 25, 'n_estimators': 800}, {'max_depth': 25, 'n_estimators': 1100}, {'max_depth': 30, 'n_estimators': 120}, {'max_depth': 30, 'n_estimators': 200}, {'max_depth': 30, 'n_estimators': 300}, {'max_depth': 30, 'n_estimators': 500}, {'max_depth': 30, 'n_estimators': 800}, {'max_depth': 30, 'n_estimators': 1100}], 'split0_test_score': array([0.83536585, 0.82926829, 0.83231707, 0.82926829, 0.82926829, 0.82926829, 0.81707317, 0.80792683, 0.80792683, 0.81097561, 0.81707317, 0.80792683, 0.79878049, 0.79878049, 0.79878049, 0.80487805, 0.79268293, 0.79573171, 0.79878049, 0.79268293, 0.79878049, 0.79878049, 0.79268293, 0.79573171, 0.79268293, 0.79268293, 0.79268293, 0.79268293, 0.79268293, 0.80182927]), 'split1_test_score': array([0.85365854, 0.85365854, 0.85060976, 0.85060976, 0.85060976, 0.85060976, 0.85365854, 0.84756098, 0.85365854, 0.84756098, 0.85365854, 0.85365854, 0.85365854, 0.8445122 , 0.85365854, 0.85365854, 0.84756098, 0.85060976, 0.84756098, 0.84756098, 0.8445122 , 0.85060976, 0.85060976, 0.85060976, 0.8445122 , 0.84756098, 0.85060976, 0.85365854, 0.85365854, 0.85060976]), 'split2_test_score': array([0.82621951, 0.82621951, 0.82317073, 0.82621951, 0.82317073, 0.82317073, 0.80182927, 0.80182927, 0.80182927, 0.80182927, 0.80182927, 0.80182927, 0.80182927, 0.80182927, 0.80182927, 0.80182927, 0.80182927, 0.80487805, 0.79878049, 0.80182927, 0.79878049, 0.80487805, 0.80487805, 0.80182927, 0.80182927, 0.80487805, 0.80487805, 0.80182927, 0.80182927, 0.80182927]), 'mean_test_score': array([0.83841463, 0.83638211, 0.83536585, 0.83536585, 0.83434959, 0.83434959, 0.82418699, 0.81910569, 0.82113821, 0.82012195, 0.82418699, 0.82113821, 0.81808943, 0.81504065, 0.81808943, 0.82012195, 0.81402439, 0.81707317, 0.81504065, 0.81402439, 0.81402439, 0.81808943, 0.81605691, 0.81605691, 0.81300813, 0.81504065, 0.81605691, 0.81605691, 0.81605691, 0.81808943]), 'std_test_score': array([0.01140749, 0.01227952, 0.01140749, 0.01085069, 0.01176406, 0.01176406, 0.02174892, 0.02027433, 0.02312969, 0.01975836, 0.02174892, 0.02312969, 0.02518193, 0.02087667, 0.02518193, 0.02374659, 0.02400612, 0.02400612, 0.02299534, 0.02400612, 0.02155813, 0.02312969, 0.02493464, 0.02455904, 0.02258751, 0.02352812, 0.02493464, 0.02684928, 0.02684928, 0.02299534]), 'rank_test_score': array([ 1, 2, 3, 3, 5, 5, 7, 13, 9, 11, 7, 9, 14, 24, 14, 11, 28, 18, 24, 28, 27, 14, 19, 19, 30, 24, 19, 19, 19, 14])}
4.6 总结
- 在当前所有算法中,随机森林具有良好的准确性
- 随机森林能够有效的运行在大数据集上,在处理高纬度特征输入样本时,不需要进行降维度处理。
- 随机森林能够评估出各个特征在分类问题上的重要性
模型选择与调优
以KNN算法为例,K的取值是不一定的,所以我们需要选择1个尽可能好的K值,取得尽可能好的结果。
那我们如何选择1个最优的K值呢,模型选择和调优就是解决这一问题的。
1.交叉验证 cross validation
交叉验证:将训练集本身再进一步划分为训练集和验证集。
如下图所示:我们将训练集分成4组,每组的其中1份作验证集,其他3份作训练集。
每次更换不同的验证,就会得到4组模型的训练结果,取4组的平均值作为最终结果。
以上这种训练集的划分过程,我们称之为交叉验证。
由于以上我们把训练集划分成了4份也称为4折交叉验证,如果划分了10组就是10折交叉验证。
优势:
以上我们充分地利用了训练集,做了多次交叉验证,这么做的好处就是可以让我们训练得出的模型结果更加准确和可信。
2.超参数搜索-网格搜索 Grid Search
在KNN算法中,如果我想知道最优的K值称为超参数,需要我们手动指定。
我只能反复地输入不同的K值不断地测试,通过暴力破解的方式得出最优的K值。
超参数搜索就是预设几个不同的超参数组合[参数1,参数2,参数3 ]。
采用网格搜索技术,对每个超参数采用交叉验证的方式对模型进行训练,最终跳出最优的参数组合。
# 用KNN算法对鸢尾花进行分类 from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import StandardScaler from sklearn.model_selection import GridSearchCV # 1.获取数据 iris = load_iris() """ attribute infromation 萼片长度(厘米) 萼片宽度(厘米) 花瓣长度(厘米) 花瓣宽度(厘米) speal_length, speal_width, petal_length, petal_width [ [5.1 3.5 1.4 0.2] [4.9 3. 1.4 0.2] [4.7 3.2 1.3 0.2] [6.2 3.4 5.4 2.3] ] ---------------------------------------------- class 0:山鸢尾 1变色鸢尾 2维吉尼亚鸢尾 [0,1,2,3] """ # print(iris.data) # print(iris.target) # 2.划分数据集 x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22) # 3.特征工程:标准化 transfer = StandardScaler() x_train = transfer.fit_transform(x_train) # 测试集继续使用训练集中fit出来的平均值和标准差,对测试集的数据进行标准化。 x_test = transfer.transform(x_test) # 4.KNN算法预估器 estimator = KNeighborsClassifier() #5.网格搜索和交叉验证 param_dict={"n_neighbors":[1,3,5,7,9,11]} estimator=GridSearchCV(estimator,param_grid=param_dict,cv=10) estimator.fit(x_train, y_train) # 6.模型评估 # 方法1:手动对比真实值和预测出来的值 y_predict = estimator.predict(x_test) print(y_test == y_predict) # 方法2:自动计算准确率 accuracy = estimator.score(x_test, y_test) print(accuracy) print("最佳参数\n",estimator.best_params_) print("最佳结果\n",estimator.best_score_) print("最佳估计器\n",estimator.best_estimator_) print("交叉验证结果\n",estimator.cv_results_)
-----------------
最佳参数 {'n_neighbors': 3} 最佳结果 0.9553030303030303 最佳估计器 KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=None, n_neighbors=3, p=2, weights='uniform') 交叉验证结果 {'mean_fit_time': array([0.00070004, 0.00020001, 0.00039999, 0.00039999, 0.00079999, 0.00049996]), 'std_fit_time': array([0.00045829, 0.00040002, 0.00048989, 0.00048989, 0.00059997, 0.00049996]), 'mean_score_time': array([0.00109999, 0.00119996, 0.00110002, 0.00099998, 0.00100002, 0.00100002]), 'std_score_time': array([2.99954433e-04, 6.00020095e-04, 3.00025978e-04, 4.47234501e-04, 1.58148994e-07, 4.47287821e-04]), 'param_n_neighbors': masked_array(data=[1, 3, 5, 7, 9, 11], mask=[False, False, False, False, False, False], fill_value='?', dtype=object), 'params': [{'n_neighbors': 1}, {'n_neighbors': 3}, {'n_neighbors': 5}, {'n_neighbors': 7}, {'n_neighbors': 9}, {'n_neighbors': 11}], 'split0_test_score': array([0.91666667, 0.91666667, 1. , 1. , 0.91666667, 0.91666667]), 'split1_test_score': array([1., 1., 1., 1., 1., 1.]), 'split2_test_score': array([0.90909091, 0.90909091, 0.90909091, 0.90909091, 0.90909091, 0.90909091]), 'split3_test_score': array([0.90909091, 1. , 0.90909091, 0.90909091, 0.90909091, 1. ]), 'split4_test_score': array([1., 1., 1., 1., 1., 1.]), 'split5_test_score': array([0.90909091, 0.90909091, 0.90909091, 0.90909091, 0.90909091, 0.90909091]), 'split6_test_score': array([0.90909091, 0.90909091, 0.90909091, 1. , 1. , 1. ]), 'split7_test_score': array([0.90909091, 0.90909091, 0.81818182, 0.81818182, 0.81818182, 0.81818182]), 'split8_test_score': array([1., 1., 1., 1., 1., 1.]), 'split9_test_score': array([1., 1., 1., 1., 1., 1.]), 'mean_test_score': array([0.94621212, 0.95530303, 0.94545455, 0.95454545, 0.94621212, 0.95530303]), 'std_test_score': array([0.04397204, 0.0447483 , 0.06030227, 0.06098367, 0.05988683, 0.0604591 ]), 'rank_test_score': array([4, 1, 6, 3, 4, 1])}
回归和聚类算法
线性回归
#波士顿房价预测 from sklearn.datasets import load_boston from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LinearRegression,SGDRegressor from sklearn.metrics import mean_squared_error #1.获取数据集 boston=load_boston() #2.划分数据集 x_train,x_test,y_train,y_test=train_test_split(boston.data,boston.target,random_state=22) #3.特征工程-标准化 transfer=StandardScaler() x_train=transfer.fit_transform(x_train) x_test=transfer.transform(x_test) #4.预估器流程 estimator=LinearRegression() estimator.fit(x_train,y_train) #5.得出模型 print("正规方程权重系数为:\n",estimator.coef_) print("正规方程偏置为:\n",estimator.intercept_) #6.模型评估 y_precit=estimator.predict(x_test) error=mean_squared_error(y_test,y_precit) print("正规方程均方误差为:\n",error) #-------------------------------------------------------- #4.预估器流程 estimator=SGDRegressor(learning_rate="constant",eta0=0.01,max_iter=20000) estimator.fit(x_train,y_train) #5.得出模型 print("梯度下降权重系数为:\n",estimator.coef_) print("梯度下降偏置为:\n",estimator.intercept_) #6.模型评估 y_precit=estimator.predict(x_test) error=mean_squared_error(y_test,y_precit) print("梯度下降的均方误差为:\n",error)
机器学习算法平台设计思想
采用工厂设计模式,封装机器学习的算法。
优势是:
工厂类实现了对象调用客户端和类服务端的解耦。
有1个专门的工厂类,接收不同的参数,实例化出不同的实例对象。
一旦类名改变,只需要在工厂类改变实例化方式即可,避免了引用该对象的地方被多处修改。
工厂模式和多态的区别:工厂模式只会返回实例,不会调用实例的方法。
参考