机器学习

1. 机器学习原理

常见名词

  • 训练数据
  • samples数据样本表
  • 训练集 X_train,y_train
  • 测试集 X_test,y_test

2. 机器学习分类

  1. 有监督学习

    • 分类
    • K近邻、朴素贝叶斯、决策树、SVM
    • 回归
    • 线性回归、逻辑回归、岭回归
  2. 无监督学习

    • 聚类
    • K-means
  3. 半监督学习

    • 深度学习

3. 深度剖析

思考

机器学习相关内容过多,错综复杂

原理及分类已经大致了解了,

还未掌握部分:

  • 各个分类下算法原理
  • 使用方法
  • 各自解决什么样的问题
  • 最终返回什么内容
3.1 k-近邻算法

原理

K-近邻算法采用测量不同特征值之间的距离方法进行分类。

  • 优点:精度高、对异常值不敏感、无数据输入假定。
  • 缺点:时间复杂度高、空间复杂度高。
  • 适用数据范围:数值型和标称型。

如上图 通过训练已知数据分析AB分类点的特征,然后给一数据,通过一定范围内该点到AB分类各点的距离来得出该点属于AB哪个分类

因为数据多、特征值不确定,所有很容易看出缺点(时间、空间复杂度高)

示例

案例一:

​ KNN算法解决电影分类问题,通过对已有数据训练,从而预测新数据属于哪类电影(爱情片/动作片)


# 读取文件
films = pd.read_excel('tests.xlsx',sheet_name=1)

samples = films[['武打镜头','接吻镜头']]
# 样本标签
target = films['分类情况']
# 创建一个新电影,武打镜头6个,接吻镜头9个
dancer = np.array([[6,9]])
# 画关系图
plt.scatter(samples['武打镜头'],samples['接吻镜头'])
plt.scatter(dancer[:,0],dancer[:,1],c='red')
plt.ylabel('kiss',fontsize=20)
plt.xlabel('action',fontsize=20)
# 构建KNN算法模型
from sklearn.neighbors import KNeighborsClassifier
knnclf = KNeighborsClassifier()

# 训练数据
knnclf.fit(samples,target)
# 预测新的样本
knnclf.predict(dancer)

scikit-learn库中使用k-近邻算法

  • 分类问题:from sklearn.neighbors import KNeighborsClassifier
  • 回归问题:from sklearn.neighbors import KNeighborsRegressor

分类问题

示例1.

身高、体重、鞋子尺码数据对应性别

并可以分析该算法的准确率

# 部分代码 提供解决问题的思想
1.获取数据样本集
    samples=pd.read_excel(...)
    # 特征
    features = samples[['身高','体重','尺码']]
    # 结果
    target = samples['性别']

2.拆分数据集(训练集、测试集)
    # 用于训练数据
    X_train = features[:8]
    y_train = target[:8]
    # 用于测试算法模型是否准确
    X_test = features[8:]
    y_test = target[8:]

3.构建算法模型对象
    # 构建算法模型对象
    from sklearn.neighbors import KNeighborsClassifier
    # 预测点跟离它最近的5个点进行比较
    knnclf = KNeighborsClassifier(n_neighbors=5)

4.训练模型
    knnclf.fit(X_train,y_train)

5.预测测试集
    y_ = knnclf.predict(X_test)

6.对结果进行评分
    可以用score()方法

示例2.鸢尾花

前面仍然是导包,读取样本集,拆分训练集测试集
问题:
# 因为鸢尾花有4个特征,无法绘制4维空间
# 所以选择前两个特征来绘制一个二维空间来查看鸢尾花的分布情况
plt.scatter(train.values[:,0],train.values[:,1],c=target)

回归问题

回归用于对趋势的预测

  1. 生成模型,训练数据
  2. 使用模型,预测数据
  3. 绘图显示数据

:生成的趋势可能欠拟合、过拟合、最佳拟合状态

欠拟合就是过于偏离真实数据(类似于判别男女,得到有眼睛 有鼻子的都是男人结论)

过拟合是过于贴近每个数据特征(类似于得到 会唱歌,姓王的都是男人结论)

例1. 随机生成一组数据,对数据添加噪声,测试最终数据是否满足预估趋势(正弦)

from sklearn.neighbors import KNeighborsRegressor
1.生成样本数据
    x = np.linspace(-np.pi,np.pi,60)
    y = np.sin(x)
    plt.scatter(x,y)
2.增加噪音
    np.random.seed(2)
    noise = np.random.random(size=30) - 0.5
    y[::2] += noise
3.生成测试数据结果
    knn = KNeighborsRegressor(n_neighbors=7)
    knn.fit(x.reshape(-1,1),y)
4.获取测试数据
    X_test = np.linspace(x.min(),x.max(),100).reshape(-1,1)
    y_ = knn.predict(X_test)
5.绘图显示
    plt.plot(X_test,y_,color='orange',label='predict')
    plt.scatter(x,y,color='green',label='true-data')
    plt.legend()

再来分析一个复杂案例

例2.判断美国一个州人群年收入与年龄、职业、工作时长、受教育程度之间的关联

思考:

  • 很明显几个特征都与年收入有关联,但有些特征(如职业)是字符无法参与运算
  • 结果(年薪)是按照”>50k”,”<50k”来显示的,也需要转换为可以参与运算的值
  • 特征之间怎样建立联系才能使结果偏差不那么大
问题解决
1.将职业这一列去重转换为相对应的映射
def mytransfunc(item):
    # 假设这个列表中的职业,从前到后,职业的相关性越来越差
    occ_unique = train['occupation'].unique()
    # 返回与职业对应的索引
    return np.argwhere(item == occ_unique)[0,0]

train['occupation'] = train['occupation'].map(mytransfunc)

2.将结果集分类
# 如果标签项并不是离散性数据,可以定义一个阈值,来对数据进行二分,或者多分
def mytargetfunc(item):
    if item == '<=50K':
        return 0
    else:
        return 1

target = target.map(mytargetfunc)

3.特征预处理
# 由于age和hours_per_week起到主导作用,所以需要进行归一处理,让各个特征对结果的影响更加公平
# 每一个数据/每一列的总和
for column in train.columns:
    train[column] = train[column]/train[column].sum()

优化数据集的方式:

  • 特征选择、归一化模型、数据清洗、降维
  • 调整参数
3.2 Linear回归算法

问题

对连续型的数据做出预测

原理

连续型的数据肯定满足线性关系Y=X*W

如果确定W?

可以使用预测Y值与真实y值差平方的累加使正负误差相互抵消,来找出误差最小的W

最小二乘法

实例

查看特征S1与血糖含量的关系

对比线性回归与knn回归的使用

1.导包、获取数据。。。
2.还是导包
    # knn
    from sklearn.neighbors import KNeighborsRegressor
    # 线性回归
    from sklearn.linear_model import LinearRegression
3.拆分训练集和结果集
4.选择knn回归和linear回归,分别进行
    knn = KNeighborsRegressor()
    line = LinearRegression()
    knn.fit(X_train,y_train)
    line.fit(X_train,y_train)
    y1_ = knn.predict(X_test)
    y2_ = line.predict(X_test)
3.3 岭回归ridge

相关小知识:

  • 矩阵,单位矩阵,方阵,逆矩阵
  • 满秩矩阵

解决问题:

  1. 数据点少于变量个数
  2. 变量间存在共线性(最小二乘回归得到的系数不稳定,方差很大)
  3. 岭回归作为一种缩减算法可以判断哪些特征重要或者不重要,有点类似于降维的效果
  4. 缩减算法可以看作是对一个模型增加偏差的同时减少方差

原理:

​ 岭回归是加了二阶正则项的最小二乘,主要适用于过拟合严重或各变量之间存在多重共线性的时候,岭回归是有bias的,这里的bias是为了让variance更小。

步骤:

  1. 训练
  2. 预测
  3. 绘制图形

示例

同时使用线性回归与岭回归处理一组数据(随机生成),

练习岭回归的同时加深下线性回归印象

1.导包...
2.生成数据
    n_samples = 50
    n_features = 200

    x = np.random.random(size=(n_samples,n_features))
    y = np.random.random(n_samples)

3.分别使用两种回归模型训练,查看两种模型的系数变化
    line = LinearRegression()
    # 调整岭回归系数,观察结果
    ridge = Ridge(alpha=30)
    # 训练
    line.fit(x,y)
    ridge.fit(x,y)
    # 系数
    coef1 = line.coef_
    coef2 = ridge.coef_
4.画图比较
    plt.plot(coef1,label='linear')
    plt.plot(coef2,label='ridge')
    plt.legend()
    # 岭回归有缩减系数的功能

【备注】coef_函数可以获取机器学习模型中各个特征值的系数

拓展:岭回归系数

1. 创建一个假象数据样本集
    X = 1. / (np.arange(1, 11) + np.arange(0, 10).reshape(-1,1))
    y = np.array([1,2,3,4,5,6,7,8,9,0])

2. 创建一个alpha集合,用以验证种不同alpha值对预测系数的结果的影响
    # 创建100个λ系数
    alphas = np.logspace(-10,-2,100)

3. 创建岭回归机器学习算法对象
4. 使用不同的alpha进行数据训练,保存所有训练结果的coef_
    ridge = Ridge()
    coefs = []
    for alpha in alphas:
        ridge.set_params(alpha=alpha)
        ridge.fit(X,y)
        coef = ridge.coef_
        coefs.append(coef)

5. 绘图查看alpha参数和coefs的关系
6. 通过岭迹线来观察alpha值的最优区间
    # alpha作为横轴 coefs作为纵轴
    plt.plot(alphas,coefs)
    plt.xscale('log')

结论

由图可以看出随系数越来越大,准确度越来越高,但λ等于0时没有意义,所以取绿色圆圈部分为最优区间最合适

3.4 lasso回归

原理:

【拉格朗日乘数法】

  • 对于参数w增加一个限定条件,能到达和岭回归一样的效果:
  • 在lambda足够小的时候,一些系数会因此被迫缩减到0

思考:

缩减系数有什么好处?

  • 对一些对结果影响不大甚至无关的特征缩减系数使之为0,
  • 降低特征维度,方便提高运算效率与准确度
  • 降低过拟合

示例

普通线性回归、岭回归与lasso回归比较
  1. 导包,并导入sklearn.metrics.r2_score用于给模型打分

  2. 使用numpy创建数据X,创建系数,对系数进行处理,对部分系数进行归零化操作,然后根据系数进行矩阵操作求得目标值

    n_samples = 50
    n_features = 200
    
    X = np.random.randint(-100,100,size=(n_samples,n_features))
    coef = np.random.random(size=200)
  3. 随机选出10个系数作为有效系数,其他全部清零

    
    # 先生成数据特征的所有索引
    
    index = np.arange(n_features)
    
    # 把索引进行随机排序
    
    np.random.shuffle(index)
    
    # 取出排序后的后190个索引
    
    zero_index = index[10:]
    coef[zero_index] = 0
  4. 增加噪声

    
    # 利用原始系数跟样本集进行点乘,得到真实的标签值
    
    y = np.dot(X,coef)
    
    # 对标签添加噪声数据
    
    np.random.seed(0)
    noise = np.random.random(50) - 0.5
    y += noise
  5. 数据训练、预测

    linear = LinearRegression()
    ridge = Ridge()
    lasso = Lasso()
    
    linear.fit(X,y)
    ridge.fit(X,y)
    lasso.fit(X,y)
  6. 数据视图,此处获取各个算法的训练数据的coef_系数

    coef1 = linear.coef_
    coef2 = ridge.coef_
    coef3 = lasso.coef_
    
    plt.figure(figsize=(10,6))
    axes1 = plt.subplot(2,2,1)
    axes1.plot(coef,color='yellow')
    axes1.set_title('true-coef')
    
    axes2 = plt.subplot(2,2,2)
    axes2.plot(coef1,color='pink')
    axes2.set_title('linear-coef')
    
    axes3 = plt.subplot(2,2,3)
    axes3.plot(coef2,color='green')
    axes3.set_title('ridge-coef')
    
    axes4 = plt.subplot(2,2,4)
    axes4.plot(coef3,color='cyan')
    axes4.set_title('lasso-coef')

结论

可以看出来,lasso回归与原数据系数图像最为拟合

但在生产中,数据并不像我们生成的这样有引导性,score得到的评分也并非那么高

所以需要我们不断的练习,凭经验选择最优方案,提高准确度

3.5 逻辑斯蒂回归logistics

思想

利用Logistics回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。这里的“回归” 一词源于最佳拟合,表示要找到最佳拟合参数集

原理:

  1. 找一个合适的预测函数h函数用来预测输入数据的判断结果,预测函数大概是线性还是非线性
  2. 构造一个Cost函数(损失函数),来表示预测的输出与训练数据类别之间的偏差,计算偏差的函数记为J(θ) 函数
  3. 显然,偏差越小预测越准,最终只需要找J(θ) 函数的最小值。这就是逻辑斯蒂回归的原理

解决问题

分类问题,名为回归 实则解决分类问题

优缺点

  • 实现简单,易于理解与实现,计算代价较低,速度快,存储资源低
  • 容易欠拟合,分类精度不高

示例:

手写数字数据集的分类

  • 导入
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
  • 处理数据
digits = datasets.load_digits()
x_digits = digits.data
y_digits = digits.target

x_train = x_digits[:round(.9*len(x_digits))]
x_test = x_digits[round(.9*len(x_digits)):]

y_train = y_digits[:round(.9*len(y_digits))]
y_test = y_digits[round(.9*len(y_digits)):]
  • 训练和预测
knn = KNeighborsClassifier()
logistic = LogisticRegression()

display('KNN score: %f'%knn.fit(x_train,y_train).score(x_test,y_test),
       'Logistic Score: %f'%logistic.fit(x_train,y_train).score(x_test,y_test))

使用make_blobs产生数据集进行分类


  • 导入
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

from sklearn.datasets import make_blobs #生成用于聚类的各向同性高斯斑点
from sklearn.linear_model import LogisticRegression
  • 处理数据
# 设置三个中心点,建立一个三分类问题
centers = [[-5,0],[0,1.5],[5,-1]]
X,y = make_blobs(n_samples=1000, centers=centers, random_state=40)
  • 训练数据
clf = LogisticRegression()
clf.fit(X,y)
  • 图片背景图片点
# 背景(网格)
h = 0.02
x_min,x_max = X[:,0].min()-1,X[:,0].max()+1
y_min,y_max = X[:,1].min()-1,X[:,1].max()+1

# 从坐标向量返回坐标矩阵
# 图片的背景显示坐标
xx,yy = np.meshgrid(np.arange(x_min,x_max,h),
                   np.arange(y_min,y_max,h))
  • 预测数据
# 得到网格上每个点的分类情况
Z = clf.predict(np.c_[xx.ravel(),yy.ravel()])
z = Z.reshape(xx.shape)
#预测背景图片的点,从而知道划分区域
  • 画图
# 画图
plt.figure()
#绘制轮廓线,填充轮廓
#plt.contourf(xx,yy,z,cmap = plt.cm.Paired)
plt.pcolormesh(xx,yy,z,cmap = plt.cm.Paired)
plt.title("Logistic Regression")
plt.axis('tight')

colors = 'bry'
for i,color in zip(clf.classes_,colors):
    idx = np.where(y==i)
    plt.scatter(X[idx,0],X[idx,1],c=color,cmap = plt.cm.Paired)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值