caiyongji

caiyongji 查看完整档案

大连编辑  |  填写毕业院校Citi  |  Application Programmer Expert 编辑 caiyongji.com 编辑
编辑

公众号: caiyongji

个人动态

caiyongji 发布了文章 · 2月25日

机器学习(五):通俗易懂决策树与随机森林及代码实践

与SVM一样,决策树是通用的机器学习算法。随机森林,顾名思义,将决策树分类器集成到一起就形成了更强大的机器学习算法。它们都是很基础但很强大的机器学习工具,虽然我们现在有更先进的算法工具来训练模型,但决策树与随机森林因其简单灵活依然广受喜爱,建议大家学习。

一、决策树

1.1 什么是决策树

我们可以把决策树想象成IF/ELSE判别式深度嵌套的二叉树形结构。以我们在《机器学习(三):理解逻辑回归及二分类、多分类代码实践》所举的鸢尾花数据集为例。

我们曾用seaborn绘制花瓣长度和宽度特征对应鸢尾花种类的散点图,如下:

image

当花瓣长度小于2.45则为山鸢尾(setosa),剩下的我们判断花瓣宽度小于1.75则为变色鸢尾(versicolor)剩下的为维吉尼亚鸢尾(virginica)。那么我用导图画一下这种判别式的树形结构如下:

image

因此,当我们面对任意鸢尾花的样本,我们只需要从根节点到叶子节点遍历决策树,就可以得到鸢尾花的分类结论。

这就是决策树。

1.2 决策树代码实践

我们导入数据集(大家不用在意这个域名),并训练模型:

import numpy as np
import pandas as pd
from sklearn.tree import DecisionTreeClassifier

#引入数据集
df = pd.read_csv('https://blog.caiyongji.com/assets/iris.csv')

#决策树模型
X = df[['petal_length','petal_width']].to_numpy() 
y = df['species']
tree_clf = DecisionTreeClassifier(max_depth=2, random_state=42)
tree_clf.fit(X, y)

我们来可视化决策树:

import matplotlib.pyplot as plt
from sklearn.tree import plot_tree
plt.figure(figsize=(12,8))
plot_tree(tree_clf,filled=True);

image

如上图,我们可以看到根节点总实例数为150时,由value = [50, 50, 50]可知,实际样本分类为50个山鸢尾花实例、50个变色鸢尾花实例、50个维吉尼亚鸢尾花实例。我们再看最末尾右侧的叶子节点(紫色),由value = [0, 1, 45]可知,实际样本分类为0个山鸢尾花实例、1个变色鸢尾花实例、45个维吉尼亚鸢尾花实例。

那么gini = 0.043是什么意思呢?

1.3 基尼不纯度

显然我们进行分类时,每一个类别实际混入其他类的数量越少分类就越纯粹,这种纯度我们通过如下公式表示:

$$ G_i = 1 - \sum_{k=1}^{n}{p^2_{i,k}} $$

我们计算维吉尼亚鸢尾花节点(紫色)的gini系数1-((0/46)**2 + (1/46)**2 + (45/46)**2) = 0.04253308128544431 ≈0.043

我们使用基尼(gini)不纯度来衡量决策树的好坏。那么我们通过最小化基尼不纯度min(gini)来求解X[0],X[1](即,花瓣长度宽度特征)边界的过程就决策树模型的训练过程。

二、随机森林

2.1 大数定理与随机森林

其实随机森林很简单,我们把决策树随机组合在一起就是随机森林,它比单个的决策树更有效。

凭什么?

假设我们有一枚不均匀的硬币,投掷它有51%的概率为正面,49%的概率为背面,那么当投掷1000次时,“大多数为正面"这件事的概率为75%。投掷10000次时,“大多数为正面"这件事的概率为97%。这就是大数定理,它体现的是群体智慧。质量不够,数量来凑。由此可知,当前寻找最佳模型的方法不止是技巧的比拼,也同样是算力的比拼。

2.2 随机森林代码实践

2.2.1. 引入新的数据集

添加引用:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

导入数据集(大家不用在意这个域名):

df = pd.read_csv("https://blog.caiyongji.com/assets/penguins_size.csv")
df = df.dropna()
df.head()
speciesislandculmen_length_mmculmen_depth_mmflipper_length_mmbody_mass_gsex
AdelieTorgersen39.118.71813750MALE
AdelieTorgersen39.517.41863800FEMALE
AdelieTorgersen40.3181953250FEMALE
AdelieTorgersen36.719.31933450FEMALE
AdelieTorgersen39.320.61903650MALE

企鹅数据集包含特征和标签如下:

  • 特征:所在岛屿island、鸟喙长度culmen_length_mm、鸟喙深度culmen_depth_mm、脚蹼长度flipper_length_mm、体重(g)、性别
  • 标签:物种species:Chinstrap, Adélie, or Gentoo

2.2.2 观察数据


sns.pairplot(df,hue='species')

我们通过pairplot方法绘制特征两两之间的对应关系。

image

2.2.3 预处理

X = pd.get_dummies(df.drop('species',axis=1),drop_first=True)
y = df['species']
X.head()

注意,get_dummies方法将字符串属性的列转换成了数字属性的多个列。如,岛屿island和性别sex分别转换成了island_Dream、island_Torgersen和sex_FEMALE、sex_MALE。这是一种独热编码的关系,比如sex_FEMALE与sex_MALE属性独立,在空间内没有向量关系。

culmen_length_mmculmen_depth_mmflipper_length_mmbody_mass_gisland_Dreamisland_Torgersensex_FEMALEsex_MALE
39.118.718137500101
39.517.418638000110
40.31819532500110
36.719.319334500110
39.320.619036500101

2.2.4 训练数据

#训练
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=101)
model = RandomForestClassifier(n_estimators=10,max_features='auto',random_state=101)
model.fit(X_train,y_train)

#预测
from sklearn.metrics import accuracy_score
preds = model.predict(X_test)
accuracy_score(y_test,preds)

使用随机森林分类器RandomForestClassifier训练,得到模型精度为97%。

2.2.5 网格搜索与AdaBoost提升法(拓展)

我们使用AdaBoostClassifier分类器集成数个决策树分类器DecisionTreeClassifier进行分类。并使用网格搜索方法GridSearchCV来寻找最优参数。

from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import AdaBoostClassifier

ada_clf = AdaBoostClassifier(DecisionTreeClassifier(max_depth=1), random_state=101)
ada_clf.fit(X_train, y_train)
param_grid = {'n_estimators':[10,15,20,25,30,35,40], 'learning_rate':[0.01,0.1,0.5,1], 'algorithm':['SAMME', 'SAMME.R']}
grid = GridSearchCV(ada_clf,param_grid)
grid.fit(X_train,y_train)
print("grid.best_params_ = ",grid.best_params_,", grid.best_score_ =" ,grid.best_score_)

这是一种集成学习技术,输出如下:

grid.best_params_ =  {'algorithm': 'SAMME', 'learning_rate': 1, 'n_estimators': 20} , grid.best_score_ = 0.9914893617021276

总结

二叉树是决策树的核心逻辑,随机森林是大数定理的应用实现。这种基本思想即使不用数学公式也可以很容易的解释清楚,这也是我做这个系列课程(文章)的主要风格特点。我认为,数学是对现实世界的解释,但现实世界并不能被数学完全解释。像谷歌AI主管Laurence Moroney所说:

很多人害怕数学,害怕大量的深度的微积分知识。其实我们可以实现编码而不考虑数学,我们可以使用TensorFlow中高(层)级的API,来解决问题,如自然语言处理,图像分类,计算机视觉序列模型等而无需理解深刻的数学。就像你使用JAVA却不一定非要掌握它是如何编译的。未来,AI只是每个开发者技术栈(toolbox)中的一部分,就像HTML, CSS, JAVA。

希望那一天可以早点到来吧……

往期文章:

查看原文

赞 0 收藏 0 评论 0

caiyongji 发布了文章 · 2月15日

机器学习(四):通俗理解支持向量机SVM及代码实践

上一篇文章我们介绍了使用逻辑回归来处理分类问题,本文我们讲一个更强大的分类模型。本文依旧侧重代码实践,你会发现我们解决问题的手段越来越丰富,问题处理起来越来越简单。

支持向量机(Support Vector Machine, SVM)是最受欢迎的机器学习模型之一。它特别适合处理中小型复杂数据集的分类任务。

一、什么是支持向量机

SMV在众多实例中寻找一个最优的决策边界,这个边界上的实例叫做支持向量,它们“支持”(支撑)分离开超平面,所以它叫支持向量机。

那么我们如何保证我们得到的决策边界是最优的呢?

image

如上图,三条黑色直线都可以完美分割数据集。由此可知,我们仅用单一直线可以得到无数个解。那么,其中怎样的直线是最优的呢?

image

如上图,我们计算直线到分割实例的距离,使得我们的直线与数据集的距离尽可能的远,那么我们就可以得到唯一的解。最大化上图虚线之间的距离就是我们的目标。而上图中重点圈出的实例就叫做支持向量。

这就是支持向量机。

二、从代码中映射理论

2.1 导入数据集

添加引用:

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

导入数据集(大家不用在意这个域名):

df = pd.read_csv('https://blog.caiyongji.com/assets/mouse_viral_study.csv')
df.head()
Med_1_mLMed_2_mLVirus Present
06.508238.582530
14.126123.073461
26.427876.369760
33.672954.905221
41.580322.440561

该数据集模拟了一项医学研究,对感染病毒的小白鼠使用不同剂量的两种药物,观察两周后小白鼠是否感染病毒。

  • 特征: 1. 药物Med_1_mL 药物Med_2_mL
  • 标签:是否感染病毒(1感染/0不感染)

2.2 观察数据

sns.scatterplot(x='Med_1_mL',y='Med_2_mL',hue='Virus Present',data=df)

我们用seaborn绘制两种药物在不同剂量特征对应感染结果的散点图。

image

sns.pairplot(df,hue='Virus Present')

我们通过pairplot方法绘制特征两两之间的对应关系。

image

我们可以做出大概的判断,当加大药物剂量可使小白鼠避免被感染。

2.3 使用SVM训练数据集

#SVC: Supprt Vector Classifier支持向量分类器
from sklearn.svm import SVC

#准备数据
y = df['Virus Present']
X = df.drop('Virus Present',axis=1) 

#定义模型
model = SVC(kernel='linear', C=1000)

#训练模型
model.fit(X, y)

# 绘制图像
# 定义绘制SVM边界方法
def plot_svm_boundary(model,X,y):
    
    X = X.values
    y = y.values
    
    # Scatter Plot
    plt.scatter(X[:, 0], X[:, 1], c=y, s=30,cmap='coolwarm')

    
    # plot the decision function
    ax = plt.gca()
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()

    # create grid to evaluate model
    xx = np.linspace(xlim[0], xlim[1], 30)
    yy = np.linspace(ylim[0], ylim[1], 30)
    YY, XX = np.meshgrid(yy, xx)
    xy = np.vstack([XX.ravel(), YY.ravel()]).T
    Z = model.decision_function(xy).reshape(XX.shape)

    # plot decision boundary and margins
    ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5,
               linestyles=['--', '-', '--'])
    # plot support vectors
    ax.scatter(model.support_vectors_[:, 0], model.support_vectors_[:, 1], s=100,
               linewidth=1, facecolors='none', edgecolors='k')
    plt.show()
plot_svm_boundary(model,X,y)

image

我们导入sklearn下的SVC(Supprt Vector Classifier)分类器,它是SVM的一种实现。

2.4 SVC参数C

SVC方法参数C代表L2正则化参数,正则化的强度与C的值城反比,即C值越大正则化强度越弱,其必须严格为正。

model = SVC(kernel='linear', C=0.05)
model.fit(X, y)
plot_svm_boundary(model,X,y)

我们减少C的值,可以看到模型拟合数据的程度减弱。

image

2.5 核技巧

SVC方法的kernel参数可取值{'linear', 'poly', 'rbf', 'sigmoid', 'precomputed'}。像前文中所使用的那样,我们可以使kernel='linear'进行线性分类。那么如果我们像进行非线性分类呢?

2.5.1 多项式内核

多项式内核kernel='poly'的原理简单来说就是,用单一特征生成多特征来拟合曲线。比如我们拓展X到y的对应关系如下:

XX^2X^3y
06.508236.50823**26.50823**30
14.126124.12612**24.12612**31
26.427876.42787**26.42787**30
33.672953.67295**23.67295**31
41.580321.58032**21.58032**31

这样我们就可以用曲线来拟合数据集。

model = SVC(kernel='poly', C=0.05,degree=5)
model.fit(X, y)
plot_svm_boundary(model,X,y)

我们使用多项式内核,并通过degree=5设置多项式的最高次数为5。我们可以看出分割出现了一定的弧度。

image

2.5.2 高斯RBF内核

SVC方法默认内核为高斯RBF,即Radial Basis Function(径向基函数)。这时我们需要引入gamma参数来控制钟形函数的形状。增加gamma值会使钟形曲线变得更窄,因此每个实例影响的范围变小,决策边界更不规则。减小gamma值会使钟形曲线变得更宽,因此每个实例的影响范围变大,决策边界更平坦。

model = SVC(kernel='rbf', C=1,gamma=0.01)
model.fit(X, y)
plot_svm_boundary(model,X,y)

image

2.6 调参技巧:网格搜索

from sklearn.model_selection import GridSearchCV
svm = SVC()
param_grid = {'C':[0.01,0.1,1],'kernel':['rbf','poly','linear','sigmoid'],'gamma':[0.01,0.1,1]}
grid = GridSearchCV(svm,param_grid)
grid.fit(X,y)
print("grid.best_params_ = ",grid.best_params_,", grid.best_score_ =" ,grid.best_score_)

我们可以通过GridSearchCV方法来遍历超参数的各种可能性来寻求最优超参数。这是通过算力碾压的方式暴力调参的手段。当然,在分析问题阶段,我们必须限定了各参数的可选范围才能应用此方法。

因为数据集太简单,我们在遍历第一种可能性时就已经得到100%的准确率了,输出如下:

grid.best_params_ =  {'C': 0.01, 'gamma': 0.01, 'kernel': 'rbf'} , grid.best_score_ = 1.0

总结

当我们处理线性可分的数据集时,可以使用SVC(kernel='linear')方法来训练数据,当然我们也可以使用更快的方法LinearSVC来训练数据,特别是当训练集特别大或特征非常多的时候。
当我们处理非线性SVM分类时,可以使用高斯RBF内核,多项式内核,sigmoid内核来进行非线性模型的的拟合。当然我们也可以通过GridSearchCV寻找最优参数。

往期文章:

查看原文

赞 1 收藏 1 评论 0

caiyongji 发布了文章 · 2月1日

机器学习(三):理解逻辑回归及二分类、多分类代码实践

本文是机器学习系列的第三篇,算上前置机器学习系列是第八篇。本文的概念相对简单,主要侧重于代码实践。
上一篇文章说到,我们可以用线性回归做预测,但显然现实生活中不止有预测的问题还有分类的问题。我们可以从预测值的类型上简单区分:连续变量的预测为回归,离散变量的预测为分类。

一、逻辑回归:二分类

1.1 理解逻辑回归

我们把连续的预测值进行人工定义,边界的一边定义为1,另一边定义为0。这样我们就把回归问题转换成了分类问题。

image

如上图,我们把连续的变量分布压制在0-1的范围内,并以0.5作为我们分类决策的边界,大于0.5的概率则判别为1,小于0.5的概率则判别为0。

image

我们无法使用无穷大和负无穷大进行算术运算,我们通过逻辑回归函数(Sigmoid函数/S型函数/Logistic函数)可以讲数值计算限定在0-1之间。

$$ \sigma(x) = \frac{1}{1+e^{-x}} $$

以上就是逻辑回归的简单解释。下面我们应用真实的数据案例来进行二分类代码实践。

1.2 代码实践 - 导入数据集

添加引用:

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

导入数据集(大家不用在意这个域名):

df = pd.read_csv('https://blog.caiyongji.com/assets/hearing_test.csv')
df.head()
agephysical_scoretest_result
3340.71
5037.21
5224.70
56310
3542.91

该数据集,对5000名参与者进行了一项实验,以研究年龄和身体健康对听力损失的影响,尤其是听高音的能力。此数据显示了研究结果对参与者进行了身体能力的评估和评分,然后必须进行音频测试(通过/不通过),以评估他们听到高频的能力。

  • 特征:1. 年龄 2. 健康得分
  • 标签:(1通过/0不通过)

1.3 观察数据

sns.scatterplot(x='age',y='physical_score',data=df,hue='test_result')

我们用seaborn绘制年龄和健康得分特征对应测试结果的散点图。

image

sns.pairplot(df,hue='test_result')

我们通过pairplot方法绘制特征两两之间的对应关系。

image

我们可以大致做出判断,当年龄超过60很难通过测试,通过测试者普遍健康得分超过30。

1.4 训练模型

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score,classification_report,plot_confusion_matrix

#准备数据
X = df.drop('test_result',axis=1)
y = df['test_result']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=50)
scaler = StandardScaler()
scaled_X_train = scaler.fit_transform(X_train)
scaled_X_test = scaler.transform(X_test)

#定义模型
log_model = LogisticRegression()

#训练模型
log_model.fit(scaled_X_train,y_train)

#预测数据
y_pred = log_model.predict(scaled_X_test)
accuracy_score(y_test,y_pred)

我们经过准备数据,定义模型为LogisticRegression逻辑回归模型,通过fit方法拟合训练数据,最后通过predict方法进行预测。
最终我们调用accuracy_score方法得到模型的准确率为92.2%。

二、模型性能评估:准确率、精确度、召回率

我们是如何得到准确率是92.2%的呢?我们调用plot_confusion_matrix方法绘制混淆矩阵。

plot_confusion_matrix(log_model,scaled_X_test,y_test)

我们观察500个测试实例,得到矩阵如下:

image

我们对以上矩阵进行定义如下:

  • 真正类TP(True Positive) :预测为正,实际结果为正。如,上图右下角285。
  • 真负类TN(True Negative) :预测为负,实际结果为负。如,上图左上角176。
  • 假正类FP(False Positive) :预测为正,实际结果为负。如,上图左下角19。
  • 假负类FN(False Negative) :预测为负,实际结果为正。如,上图右上角20。

准确率(Accuracy) 公式如下:

$$ Accuracy = \frac{TP+TN}{TP+TN+FP+FN} $$

带入本例得:

$$ Accuracy = \frac{285+176}{285+176+20+19} = 0.922 $$

精确度(Precision) 公式如下:

$$ Precision = \frac{TP}{TP+FP} $$

带入本例得:
$$ Precision = \frac{285}{285+19} = 0.9375 $$

召回率(Recall) 公式如下:

$$ Recall = \frac{TP}{TP+FN} $$

带入本例得:

$$ Recall = \frac{285}{285+20} = 0.934 $$

我们调用classification_report方法可验证结果。

print(classification_report(y_test,y_pred))

image

三、Softmax:多分类

3.1 理解softmax多元逻辑回归

Logistic回归和Softmax回归都是基于线性回归的分类模型,两者无本质区别,都是从伯努利分结合最大对数似然估计。

最大似然估计:简单来说,最大似然估计就是利用已知的样本结果信息,反推最具有可能(最大概率)导致这些样本结果出现的模型参数值。

术语“概率”(probability)和“似然”(likelihood)在英语中经常互换使用,但是它们在统计学中的含义却大不相同。给定具有一些参数θ的统计模型,用“概率”一词描述未来的结果x的合理性(知道参数值θ),而用“似然”一词表示描述在知道结果x之后,一组特定的参数值θ的合理性。

Softmax回归模型首先计算出每个类的分数,然后对这些分数应用softmax函数,估计每个类的概率。我们预测具有最高估计概率的类,简单来说就是找得分最高的类。

3.2 代码实践 - 导入数据集

导入数据集(大家不用在意这个域名):

df = pd.read_csv('https://blog.caiyongji.com/assets/iris.csv')
df.head()
sepal_lengthsepal_widthpetal_lengthpetal_widthspecies
5.13.51.40.2setosa
4.931.40.2setosa
4.73.21.30.2setosa
4.63.11.50.2setosa
53.61.40.2setosa

该数据集,包含150个鸢尾花样本数据,数据特征包含花瓣的长度和宽度和萼片的长度和宽度,包含三个属种的鸢尾花,分别是山鸢尾(setosa)、变色鸢尾(versicolor)和维吉尼亚鸢尾(virginica)。

  • 特征:1. 花萼长度 2. 花萼宽度 3. 花瓣长度 4 花萼宽度
  • 标签:种类:山鸢尾(setosa)、变色鸢尾(versicolor)和维吉尼亚鸢尾(virginica)

3.3 观察数据

sns.scatterplot(x='sepal_length',y='sepal_width',data=df,hue='species')

我们用seaborn绘制花萼长度和宽度特征对应鸢尾花种类的散点图。

image

sns.scatterplot(x='petal_length',y='petal_width',data=df,hue='species')

我们用seaborn绘制花瓣长度和宽度特征对应鸢尾花种类的散点图。

image

sns.pairplot(df,hue='species')

我们通过pairplot方法绘制特征两两之间的对应关系。

image

我们可以大致做出判断,综合考虑花瓣和花萼尺寸最小的为山鸢尾花,中等尺寸的为变色鸢尾花,尺寸最大的为维吉尼亚鸢尾花。

3.4 训练模型

#准备数据
X = df.drop('species',axis=1)
y = df['species']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=50)
scaler = StandardScaler()
scaled_X_train = scaler.fit_transform(X_train)
scaled_X_test = scaler.transform(X_test)

#定义模型
softmax_model = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10, random_state=50)

#训练模型
softmax_model.fit(scaled_X_train,y_train)

#预测数据
y_pred = softmax_model.predict(scaled_X_test)
accuracy_score(y_test,y_pred)

我们经过准备数据,定义模型LogisticRegressionmulti_class="multinomial"多元逻辑回归模型,设置求解器为lbfgs,通过fit方法拟合训练数据,最后通过predict方法进行预测。
最终我们调用accuracy_score方法得到模型的准确率为92.1%。

我们调用classification_report方法查看准确率、精确度、召回率。

print(classification_report(y_test,y_pred))

image

3.5 拓展:绘制花瓣分类

我们仅提取花瓣长度和花瓣宽度的特征来绘制鸢尾花的分类图像。

#提取特征
X = df[['petal_length','petal_width']].to_numpy() 
y = df["species"].factorize(['setosa', 'versicolor','virginica'])[0]

#定义模型
softmax_reg = LogisticRegression(multi_class="multinomial",solver="lbfgs", C=10, random_state=50)

#训练模型
softmax_reg.fit(X, y)

#随机测试数据
x0, x1 = np.meshgrid(
        np.linspace(0, 8, 500).reshape(-1, 1),
        np.linspace(0, 3.5, 200).reshape(-1, 1),
    )
X_new = np.c_[x0.ravel(), x1.ravel()]

#预测
y_proba = softmax_reg.predict_proba(X_new)
y_predict = softmax_reg.predict(X_new)

#绘制图像
zz1 = y_proba[:, 1].reshape(x0.shape)
zz = y_predict.reshape(x0.shape)
plt.figure(figsize=(10, 4))
plt.plot(X[y==2, 0], X[y==2, 1], "g^", label="Iris virginica")
plt.plot(X[y==1, 0], X[y==1, 1], "bs", label="Iris versicolor")
plt.plot(X[y==0, 0], X[y==0, 1], "yo", label="Iris setosa")
from matplotlib.colors import ListedColormap
custom_cmap = ListedColormap(['#fafab0','#9898ff','#a0faa0'])
plt.contourf(x0, x1, zz, cmap=custom_cmap)
contour = plt.contour(x0, x1, zz1, cmap=plt.cm.brg)
plt.clabel(contour, inline=1, fontsize=12)
plt.xlabel("Petal length", fontsize=14)
plt.ylabel("Petal width", fontsize=14)
plt.legend(loc="center left", fontsize=14)
plt.axis([0, 7, 0, 3.5])
plt.show()

得到鸢尾花根据花瓣分类的图像如下:

image

四、小结

相比于概念的理解,本文更侧重上手实践,通过动手编程你应该有“手热”的感觉了。截至到本文,你应该对机器学习的概念有了一定的掌握,我们简单梳理一下:

  1. 机器学习的分类
  2. 机器学习的工业化流程
  3. 特征、标签、实例、模型的概念
  4. 过拟合、欠拟合
  5. 损失函数、最小二乘法
  6. 梯度下降、学习率

7.线性回归、逻辑回归、多项式回归、逐步回归、岭回归、套索(Lasso)回归、弹性网络(ElasticNet)回归是最常用的回归技术

  1. Sigmoid函数、Softmax函数、最大似然估计

如果你还有不清楚的地方请参考:

查看原文

赞 0 收藏 0 评论 0

caiyongji 发布了文章 · 1月19日

机器学习(二):理解线性回归与梯度下降并做简单预测

预测从瞎猜开始

上一篇文章所说,机器学习是应用数学方法在数据中发现规律的过程。既然数学是对现实世界的解释,那么我们回归现实世界,做一些对照的想象。

想象我们面前有一块塑料泡沫做的白板,白板上分布排列着数枚蓝色的图钉,隐约地它们似乎存在着某种规律,我们试着找出规律。

image

白板上的图钉(数据)如上图所示,我们有没有一种方法(数学算法)来寻找规律(模型解释)呢? 既然不知道怎么做,那我们瞎猜吧!

我拿起两根木棒在白板前比划,试着用木棒表示数据的规律。我随便放了放,如下图所示:

image

它们似乎都在一定程度上能表示蓝色图钉的规律,那么问题来了,绿色(虚线)和红色(实线)哪一个表示更好呢?

损失函数(成本函数)

好与坏是很主观的表达,主观的感受是不可靠的,我们必须找到一种客观的度量方式。我们想当然的认为误差最小的表示,是最好的。那么,我们引出一种量化误差的方法---最小二乘法。

最小二乘法:使误差的平方和最小的办法,是一种误差统计方法,二乘就是平方的意思。
$$ SE = \sum{(y_{pred} -y_{true})^2} $$

最小二乘法的解释是这样的,我们用预测值-实际值表示单点的误差,再把它们的平方和加到一起来表示整体误差。(平方的好处可以处理掉负数值,用绝对值的和也不是不可以。)我们用这个最终值来表示损失(成本),而可以表示损失(成本)的函数就叫做损失函数(成本函数)。

image

如上图我们可以看到,蓝色点到实线的距离就是我们要带入公式的误差。虽然它们看上去相近,但经过计算的结果是红色实线(y=3x+2)的损失为27.03,而绿色实线(y=4x+4)的损失为29.54,显然红色模型优于绿色模型。

那么,还有没有比红色实线更好的模型来表示数据呢?有没有一种方式来找到它呢?

梯度下降

我们把木棒(实线、模型)的表示数学化,我们既然可以用3、4做为x的系数,那我们当然可以尝试别的数字。我们用如下公式表示这种关系:

$$ y = wx + b $$

其中,x和y是已知的,我们不断调整w(权重)和b(偏差),然后再带入损失函数以求得最小值的过程,就是梯度下降

我们从-50开始到50结束设置w的值,我们通过随机数来是指偏置b,然后再带入损失函数计算我们的预测和实际值的误差损失,得到如下曲线:

image

需要注意的是,我们绘制的图像是根据权重和损失绘制的曲线。而我们的模型表示是一条直线。
我们可以看到,在上图中我们是可以找到极小值的,大概在5左右,此处是我们损失最小的位置,这时我们的模型最能表示数据的规律。

梯度可以完全理解为导数,梯度下降的过程就是我们不断求导的过程。

学习率(步长)

不断调整权重和偏差来来寻找损失函数最小值的过程就是我们使用梯度下降方法拟合数据寻找最佳模型的过程。那么既然我们有了解决方案,是不是该考虑如何提升效率了,我们如何快速地找到最低点?

想象一下,当你迷失在山上的浓雾之中,你能感觉到的只有你脚下路面的坡度。快速到达山脚的一个策略就是沿着最陡的方向下坡。梯度下降中的一个重要的参数就是每一步的步长学习率),如果步长太小,算法需要经过大量迭代才会收敛,如果步长太大,你可能会直接越过山谷,导致算法发散,值越来越大。

设置步长为过小:

image

设置步长过大:

image

设置步长适当:

image

步长是算法自己学习不出来的,它必须由外界指定。
这种算法不能学习,需要人为设定的参数,就叫做超参数

线性回归

最终我们找到了线性模型来解释自变量x与因变量y之间的关系,这就是线性回归。回归的解释是,事物总是倾向于朝着某种“平均”发展,这种趋势叫做回归,所以回归多用于预测。

image

上图,红线是我们拟合出的最佳模型,在此模型上我们可以寻找到2.2,2.6,2.8的预测值,分别对应图中的三个红点。

这也是线性回归的基本意义。

代码实践

准备数据:

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)
X = 2 * np.random.rand(10)
y = 4 + 3 * X + np.random.randn(10)

plt.plot(X, y, "bo")
plt.xlabel("$X$", fontsize=18)
plt.ylabel("$y$", rotation=0, fontsize=18)
plt.axis([0, 2, 0, 15])
plt.show()

绘制y=3x+2y=4x+4两条直线:

plt.plot(X, y, "bo")
plt.plot(X, 3*X+2, "r-", lw="5", label = "y=3x+2")
plt.plot(X, 4*X+4, "g:", lw="5", label = "y=4x+4")
plt.xlabel("$X$", fontsize=18)
plt.ylabel("$y$", rotation=0, fontsize=18)
plt.axis([0, 2, 0, 15])
plt.legend(loc="upper left")
plt.show()

计算损失,并比较y=3x+2y=4x+4两条直线:

fig, ax_list = plt.subplots(nrows=1, ncols=2,figsize=(20,10))
ax_list[0].plot(X, y, "bo")
ax_list[0].plot(X, 3*X+2, "r-", lw="5", label = "y=3x+2")
loss = 0
for i in range(10):
    ax_list[0].plot([X[i],X[i]], [y[i],3*X[i]+2], color='grey')
    loss= loss + np.square(3*X[i]+2-y[i])
    pass
ax_list[0].axis([0, 2, 0, 15])
ax_list[0].legend(loc="upper left")
ax_list[0].title.set_text('loss=%s'%loss)


ax_list[1].plot(X, y, "bo")
ax_list[1].plot(X, 4*X+4, "g:", lw="5", label = "y=4x+4")
loss = 0
for i in range(10):
    ax_list[1].plot([X[i],X[i]], [y[i],4*X[i]+4], color='grey')
    loss= loss + np.square(4*X[i]+4-y[i])
    pass
ax_list[1].axis([0, 2, 0, 15])
ax_list[1].legend(loc="upper left")
ax_list[1].title.set_text('loss=%s'%loss)
fig.subplots_adjust(wspace=0.1,hspace=0.5)
fig.suptitle("Calculate loss",fontsize=16)

训练模型,并预测:

from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X.reshape(-1,1),y.reshape(-1,1))

X_test = [[2.2],[2.6],[2.8]]
y_test = lr.predict(X_test)
X_pred = 3 * np.random.rand(100, 1)
y_pred = lr.predict(X_pred)
plt.scatter(X,y, c='b', label='real')
plt.plot(X_test,y_test, 'r', label='predicted point' ,marker=".", ms=20)
plt.plot(X_pred,y_pred, 'r-', label='predicted')
plt.xlabel("$X$", fontsize=18)
plt.ylabel("$y$", rotation=0, fontsize=18)
plt.axis([0, 3, 0, 15])
plt.legend(loc="upper left")
loss = 0
for i in range(10):
    loss = loss + np.square(y[i]-lr.predict([[X[i]]]))
plt.title("loss=%s"%loss)
plt.show()

其他回归

要怎么真正理解回归(regression)呢?通过大量的数据统计,个体小的豆子往往倾向于产生比其更大的后代,而个体大的豆子往往倾向于产生比其更小的后代,新产生的个体有向着豆子的平均值的一种趋势,这种趋势就是回归。我们本篇文章讲的线性回归就是应用于预测的一种技术。这时,回归往往与分类相对。

线性回归、逻辑回归、多项式回归、逐步回归、岭回归、套索(Lasso)回归、弹性网络(ElasticNet)回归是最常用的回归技术。我先对这些技术做一个简单整理,让大家把脉络理清,等大家实际需要再深入探索。试图去穷尽知识只会把自己拖向疲累

名称解释公式
线性回归(Linear Regression)一种以线性模型来建模自变量与因变量关系的方法$$ y = wx+b $$
逻辑回归(Logistic Regression)对特定类别进行建模,用于二分类$$ y=\frac{1}{1+e^{-x}} $$
多项式回归(Polynomial Regression)自变量 x 和因变量 y 之间的关系被建模为关于 x 的 n 次多项式$$ y=\beta_0 + \beta_1x + \beta_2x^2 + ... + \beta_mx^m + \varepsilon $$ (cαiyongji水印)
逐步回归(Stepwise Regression)将多个变量一个一个地引入到模型,找到其对模型影响大的变量
套索回归(Lasso Regression)稀疏矩阵,消除不重要的特征,MSE+L1范数$$ J(\theta)=MSE(\theta) + \alpha\sum\mid\theta\mid $$ ,其中,α越大模型权重越小
岭回归(Ridge Regression)正则化线性回归,增加模型自由度,防止过拟合,MSE+L2范数$$ J(\theta)=MSE(\theta) + \alpha\frac{1}{2}\sum\theta^2 $$ ,其中,α越大模型权重越小
弹性网络(ElasticNet)介于岭回归和Lasso回归之间$$ J(\theta)=MSE(\theta) + \gamma\alpha\sum\mid\theta\mid + \alpha\frac{1-\gamma}{2}\sum\theta^2 $$ ,其中,γ介于0和1之间,接近0则更倾向于岭回归,接近1则更倾向于Lasso回归
查看原文

赞 0 收藏 0 评论 0

caiyongji 发布了文章 · 1月16日

机器学习(一):5分钟理解机器学习并上手实践

引言

现在市面上的机器学习教程大多先学习数学基础,然后学机器学习的数学算法,再建立机器学习的数学模型,再学习深度学习,再学习工程化,再考虑落地。这其中每个环节都在快速发展,唯独落地特别困难。我们花费大量时间成本去学习以上内容,成本无疑是特别昂贵的。所以我们不如先“盲人摸象”、“不求甚解”地探索下机器学习,浅尝辄止。如果想到自己的应用场景,再学以致用,深入探索。这无疑是使沉没成本最低的决策。
本教程适合兴趣广泛的人士增加自己知识的广度,从应用的角度谨“使用”机器学习这款工具,是典型的黑盒思维。这非常契合笔者的思维方式,当然也是我个人的格局局限。
本教程会浅显易懂,让你走的很快。但如果你想走的更远还请学习数学。当然我们也只是暂时放下数学,先构建自己的知识体系。

先抬头看路,找准适合自己的方向,再埋头赶路,或深耕下去……

把视角拉高

从手工到工业化再到人工智能,这是把人类从生产活动中逐渐解放的过程。用机器来帮助人们工作,一直是人类的美好愿望。让机器智能化,以此来代替人力做更智能问题,这可以作为人工智能的简单解释。
很多教程或者书籍把人工智能、机器学习、深度学习的关系解释为从属关系,人工智能 > 机器学习 > 深度学习。这种解释不错,但却无法表示他们之间的更深层次的关系。
机器学习是通过数学方法在数据中寻找解释,以此来实现人工智能的一种手段。而深度学习是参照神经系统在机器学习基础上发展出的一种高级技巧。 它们之间是存在一定的依托关系、进化趋势的。
狭义地讲,传统的机器学习是通过数学模型不断求导来找出数据规律的过程。这其中数学模型的选择尤为重要。随着GPU、TPU等算力的发展,算法技术的进步,甚至出现了自动选模型、自动调参的技术。我们可以构建复杂的神经网络结构,只要有足够的算力支持,足够的时间我们可以用深度学习处理非常复杂的任务。所以在代码操作上,深度学习甚至比传统的机器学习对程序员更友好、更易理解。我们先学习传统机器学习而非直接学习深度学习的好处是,我们可以通过对“黑盒”的拆箱来理解机器学习过程,掌握机器学习的概念,我会对其中应用的数学模型进行解释。

我们先来看一下人工智能产业链的结构,如下图:

image

我们可以看到,机器学习的三大基石---算力、算法与数据。机器学习的发展离不开算法数学的进步,同样离不开算力的发展。
在技术层面,机器学习在计算机视觉(CV, Computer Vision)和自然语言处理(NLP, Nature Language Processing)取得了关键的发展和应用。
算法分类上,机器学习分为监督学习、非监督学习、半监督学习、强化学习等。

  • 监督学习:数据样本有标签。
  • 非监督学习:数据样本无标签。
  • 半监督学习:数据样本有部分(少量)标签。
  • 强化学习:趋向结果则奖励,偏离结果则惩罚。

所谓Garbage in, Garbage out(垃圾进,垃圾出)。数据是机器学习的重中之重。我们需要花费大量的时间来处理数据,甚至占到整个机器学习任务的90%以上。
比如数据处理过程中的数据采集,如果我们采样的方式欠妥,就可能导致非代表性的数据集,这就导致了采样偏差。
我们的数据可能会有很多无效的数据,我们需要剔除无效的数据,就叫做数据清洗。
我们通过挖掘大量数据来发现不太明显的规律,就称作数据挖掘。

机器学习工业化流程

我们以一款工业化流水线工具TFX为例,看一下机器学习的技术流程。

image

流程分为数据输入、数据验证、特征工程、训练模型、验证模型、应用良好模型和提供模型六个部分:

  1. 输入数据,并根据需要拆分数据集。
  2. 生成训练数据和服务数据的特征统计信息。通过从训练数据中推断出类型、类别和范围来创建架构。识别训练数据和服务数据中的异常值。
  3. 对数据集执行特征工程。
  4. 训练模型,调整模型的超参数。
  5. 对训练结果进行深入分析,并帮助验证导出的模型。检查模型是否确实可以从基础架构提供服务,并防止推送不良模型。
  6. 将模型部署到服务基础架构。

我想通过以上解释,大家应该可以对机器学习的实践方法有了一定宏观的了解。

机器是如何学习的

我们从宏观角度看了机器学习的产业结构、工业化流程,你应该对你自己在机器学习的这些环节中有哪些发挥有了一定的把握。现在我们把视角拉回到微观层面,看看机器是如何学习的。

我们以摄氏度转换华氏度为例。
传统编程中,我们要求得摄氏度和华氏度的关系,我们必须找出公式:
$$ Fahrenheit = Celsius * 1.8 + 32 $$

而在对机器学习来说,我们有大量的数据,却需要找出关系。机器学习的过程就是不断求导,以此来找出数学模型,来解释规律的过程。

image

如图所示,我们有摄氏度数据0, 8, 15, 22, 38以及华氏度数据32, 46.4, 59, 71.6, 100.4,机器学习的过程就是找出公式的过程。
其中,摄氏度就是我们的特征,华氏度就是我们的标签,摄氏度与华氏度的关系就是实例

  • 特征:我们模型的输入。 在这种情况下,只有一个值-摄氏度。
  • 标签:我们的模型预测的输出。 在这种情况下,只有一个值-华氏度。
  • 实例:训练期间使用的一对输入/输出。 在我们的例子中,是摄氏度/华氏度一对数据,例如,(0, 32), (8, 46.4)。

蓝色的部分表示我们设置好数学函数,然后通过不断的调整权重与偏差不断地拟合数据,最终得到可以表示规律的模型的过程。

  • 拟合:通过训练数据,使模型来概括表示数据的过程。
  • 模型:图结构,包含了训练过程中的权重与偏差的数据。其中的图为由各函数组成的计算结构。

简单上手机器学习代码

在上手代码之前我默认你已经配置好了环境,掌握了Jupyter, Numpy, Pandas, Matplotlib的用法。如果你没有掌握以上技能,请参考我写的配套教程前置机器学习系列

import numpy as np
import matplotlib.pyplot as plt
celsius    = [[-40], [-10], [ 0], [ 8], [15], [22], [ 38]]
fahrenheit = [[-40], [ 14], [32], [46.4], [59], [71.6], [100.4]]
plt.scatter(celsius,fahrenheit, c='red', label='real')
plt.xlabel('celsius')
plt.ylabel('fahrenheit')
plt.legend()
plt.grid(True)
plt.title('real data')
plt.show()

如上代码所示,我们准备摄氏度与华氏度的数据,然后通过matplotlib库绘制图像。

image

from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(celsius,fahrenheit)

我们通过上方仅仅3行代码就训练了数据。LinearRegression是scikit-learn包下的线性回归方法,是普通的最小二乘线性回归。而fit就是拟合的意思,以此来训练模型。

celsius_test = [[-50],[-30],[10],[20],[50],[70]]
fahrenheit_test = lr.predict(celsius_test)
plt.scatter(celsius,fahrenheit, c='red', label='real')
plt.scatter(celsius_test,fahrenheit_test, c='orange', label='predicted')
plt.xlabel('celsius')
plt.ylabel('fahrenheit')
plt.legend()
plt.grid(True)
plt.title('estimated vs real data')
plt.show()

接下来我们调用lr.predict(celsius_test)方法来进行预测,以此来检验我们的模型准确度。我们通过下方图像中黄色的点可以看出,我们的模型非常准确。

image

你就说这玩意简单不简单! 咳咳,别嚣张,我们好好玩。

顺带一提的深度学习代码

既然都上手了,我们也试一试深度学习代码:

import tensorflow as tf
import numpy as np

# prepare data
celsius_q    = np.array([-40, -10,  0,  8, 15, 22,  38],  dtype=float)
fahrenheit_a = np.array([-40,  14, 32, 46.4, 59, 71.6, 100.4],  dtype=float)

# fit model
model = tf.keras.Sequential([tf.keras.layers.Dense(units=1, input_shape=[1])])
model.compile(loss='mean_squared_error', optimizer=tf.keras.optimizers.Adam(0.1))
history = model.fit(celsius_q, fahrenheit_a, epochs=500, verbose=False)
print("Finished training the model")

# print loss
import matplotlib.pyplot as plt
plt.xlabel('Epoch Number')
plt.ylabel("Loss Magnitude")
plt.plot(history.history['loss'])

我们使用TensorFlow内置的Keras方法创建了1层的神经网络,选择了MSE损失函数以及Adam优化器,训练了500代。

如下图可以看到,随着代(epoch)数量的增加,损失函数的结果逐渐降低。

image

那么什么是损失函数呢?我们在接下来的文章中一探究竟。感谢您的关注公众号【caiyongji】与支持!

前置学习系列

查看原文

赞 0 收藏 0 评论 0

caiyongji 分享了头条 · 2020-12-31

文末有红包🧧现金💰书籍📖赠送。

赞 1 收藏 0 评论 1

caiyongji 发布了文章 · 2020-12-31

2021,新世界!

如果我们不能击败它,就必须与之共存。

随便聊聊。文末有红包🧧现金💰书籍📖赠送。

新冠病毒正在彻底改变世界,人类与之斗争,没有人敢断言结果。我们做职业规划、人生规划时,要重新考虑风险。

中国崛起

IMF预计,中国是2020年全球唯一一个经济正增长的主要经济体。

中国在悠悠的历史长河中,一直不是以民主为核心的。我们受孔孟思想的影响深远,我们尊师重道,信仰真理,追随权威。当面对灾难时,这尤其有效,我们让最有能力的人做决定,听从他的一切指挥,脱离困境。这是人民出让权力,政府执行软强制主义的典型方式。它显然比所谓的“可操控的民主”更高级,更何况随着社会的进步,中国在一点点将人民的权力归还给人民。这种信任让中国人比任何国家都团结,我们认准的方向,都是无人能挡的,无论对错。

这让中国的拳头是最硬的。

当然中国有中国的问题,但无疑我们不该忽略中国巨大的优势。疫情前很多有钱的朋友在讲海外资产配置,现在在考虑把热钱留在中国。我想很大的原因就是因为中国更安全。我听说某个F家的朋友一直远程办公,2020年初去三亚度假,然后全年在三亚工作(度假)。

行业变化

谈生活之前不得不谈行业。

虽然很多传统行业不得不需要线下人员参与,但我相信我的读者大多偏向于互联网、IT、软件产业。我们有脱离线下转到线上的机会,这是我们的优势,我们可以坦然的承认这一点。

传统行业,比如农行、制造业重要吗?相当重要。但我们过了只追求吃饱穿暖的阶段了,我们有了更高的追求,我们扬帆起航追求的是星辰大海……

有人说,没人种田你们所有人都会饿死。其实不是的,这只是固守在传统行业上的人的嫉妒罢了。如果真的没人种田了,国家会有统一的、机械的、标准化的农耕方式来代替人力。这时多余的人力还是要转移到新兴的行业上去。这只是时间早晚的问题。历史的车轮没有任何人可以阻止,我们顺应着时代才能让自己过的更好。

这个世界不惩罚墨守成规的人,它会只奖励那些拥抱变化的人,渐渐地那些站在原地的人就被多数人落下了。举个简单的例子,我们不惩罚单身的人,但会给有孩子的人减免个税。

快递、外卖、远程会议,网课、网红、直播带货。 这些是2020年新钱的主要流向的典型例子。直播经济、网红经济、娱乐经济,很多人对此是嗤之以鼻的,我只是想说我们别着急否定他们,有时候困住你的恰恰是你自己的旧思想,那些条条框框。如果我说有些人一年赚到的钱是别人300年赚到的钱呢?或许他们的收入不稳定,但你能活到300岁吗?

虽然个例不代表整个行业,但它能代表行业趋势。有时候我们承认别人优秀,才能自己和自己真正地和解。

生活变化

再具体到生活谈变化。

还记得2010年的主流手机是什么?没错,10年前诺基亚还是大哥,流量1M一块钱。10年后的今天,流量1G一块钱,人们实时语音,视频通话。很多没等官方通报,视频已经在群里传飞起来了。
今年(2020年)我在的园区场地着火,先是日本的朋友发给我的消息,我才抬头看到窗外的浓烟。不查领导酒驾的交警,不戴口罩防疫的干部,不让群众使用卫生间的机关,10年前没人想到贪腐是靠互联网整治的。信息的超快速传输已经彻底改变了我们的生活。中国山区田园生活的景象可以传到纽约,我们可以看卖翡翠的演员忍痛割爱,甚至远隔万里的情侣也可以有别样的情趣……咳咳。

沟通的方式变了,购物的方式变了。我们的世界变好了也变坏了,但绝对和以前不一样了。也许有些技术并不稀奇,几年甚至几十年前就有了,但以前成本高昂,现在普及量产还可以再送你两桶都有,让普通百姓用得起了,这就很了不起。我看到一个短视频里,有学生被叫到黑板前做题,下面的同学用蓝牙耳机偷偷告诉他答案了。

我终于可以说那句话了,你的孩子生活在你永远无法想象的未来,你甚至连做梦都梦不到。

Your children are not your children.
They are the sons and daughters of Life's longing for itself.
They come through you but not from you,
And though they are with you, yet they belong not to you.
You may give them your love but not your thoughts,
For they have their own thoughts.
You may house their bodies but not their souls,
For their souls dwell in the house of tomorrow,
which you cannot visit, not even in your dreams.

---Kahlil Gibran

拥抱变化

我表达一下我自己浅薄的看法,为了让意见有更多参考的价值,我不会说一些模棱两可却正确的话。我的表述可能不严谨、很狭隘,但应该会很直接、很有用。如果你发现我语言或逻辑上的漏洞请参考互联网上的其他知识自行判断,兼听则明。每个道理都有其有限的作用范围,也跟每个人的认知偏差有关,不能一概而论,也无需争论对错。

世界看中国,中国看北京。

随着“内循环”政策的提出,北京的地位变得更加重要,超过了长三角、珠三角经济区的地位。无疑是老大中的老大。以后北京无疑是中国天花板最高的城市。

选择城市就像爬山,在爬之前你并不知道你能爬多高,但如果你足够优秀,你在一个小山头很容易爬到山顶,当你想换一座山的时候,成本无疑是非常高的。一线城市有更多、更好的机会,它们永远有足够大的舞台让你发挥。如果不是舞台不够大,是你不够强,或者你不想去争名逐利,二三线甚至十八线城市也可以让人活得很舒服。

抛下北京不谈,我认为新的城市优先级会从南到北排序,深圳、环深圳、上海、环上海、海南。

线下转线上。

如果你有机会一定要让自己尽量的靠近线上。跟着新钱走,有机会。远离实体接触,更安全。脱离坐班,更自由。

而时间自由是实现财务自由的第一步。

线上的机会太多了,大家尽量选择门槛高的,能发挥自己优势的领域。一是避免过分竞争,杀入一片红海,生存还是很难的。二是用自己的特长、高门槛来构建壁垒,让自己有竞争力,可以持续发展,而不是一锤子买卖。

你自己独一无二的灵感。

试试呗?加油。

AI未来

目前,人工智能非常适合简单的、重复性的工作。

AI在医学领域有大量的应用,但它无法代替医生,很长一段时间内都不可能。AI在自动驾驶领域有高速的发展,但它无法代替司机,小范围的有限条件下后续可以,但无法普及。AI还没有强大到代替专业的人,但它可以做为辅助手段帮助专家,节省专家的精力。

在可以预见的未来,AI会取代那些低技术含量、做重复工作的劳动力。理由很简单,AI不用保险、AI不会抱怨、AI不用休息,无需年假、奖金。AI稳定且高效,它不会因为与老婆吵架而工作不在状态,也不会因为连续工作24小时而效率下降,甚至AI可以在毫秒级内做出人类无法做出的连续反应。

比如公务员、银行职员。目前很多大银行推出的无人银行的概念已经足够说明了,这点我就不具体说了。说说公务员,我指的是公务员中那些技术含量低的工作,也就是那些所谓的钱多事少的工作。越是容易的、简单的工作越容易被取代,以后追求稳定可以,太清闲就别想了,提升自己的一技之长才是正道。我为什么这么说呢,因为我已经见到有AI公司和政府部门洽谈合作了。

(注意:每种职业都有不可替代的努力的、勤奋的人,我尊重每一个职业。上文单单指价值产出少,可替代性强的工作内容。)

打工人还是打工人,工具人终被工具替代。

拥抱AI

其实你问问中国最优秀的那批人,世界将会怎样?他们也不知道。唯一可以确定的是,没人可以阻挡世界的发展,除了顺从你别无选择。AI正在取代一些人的工作,虽然残酷,但这是事实。

有人觉得AI是博士、研究生从事的行业,至少要有计算机,数学的背景。一提数学就头大。其实大可不必。2020年5月,韩国TFUG邀请谷歌的AI主管Laurence Moroney进行了一次采访,我有幸听到他对AI的看法,我这里简单翻译下他的意思,并不是他的原话。

很多人害怕数学,害怕大量的深度的微积分知识。其实我们可以实现编码而不考虑数学,我们可以使用TensorFlow中高(层)级的API,来解决问题,如自然语言处理,图像分类,计算机视觉序列模型等而无需理解深刻的数学。就像你使用JAVA却不一定非要掌握它是如何编译的。未来,AI只是每个开发者技术栈(toolbox)中的一部分,就像HTML, CSS, JAVA。

参考Youtube 4分06秒:https://www.youtube.com/watch?v=8kMaqQNubNA

其实,对于先避开数学接触机器学习,再试着深入了解原理,这种方式我是非常认可的。我们不见得要跑到所有人的最前面,我们勇敢的往这个方向走就可以了。先当“调包侠”如果有机会再当“调参侠”也是不错的选择。

我正在写这方面的教程,我的方式就是先避开数学,先看看机器学习究竟长什么样,再去深入它的理论。大家可以关注我,公众号【caiyongji】,2021年我会不断的更新AI方向的原创文章,包括人工智能科普、机器学习教程。

说回新冠

早在2月份的时候我看了朋友给我发的关于新冠病毒的论文,它和艾滋病有着某种程度的相似,我想了想最近几十年来医学界在艾滋病领域的发展,说实话,我是悲观的。随着欧洲病毒的变异,我想我们真的需要认真对待,做好与之长期相处的准备。世界正在改变,2021年的新世界,我们要顺应新的规则。先保护好自己,再来爱这个世界。

爱惜自己

大家可以选择996,但一定要记得爱惜自己。我们不知道明天和死亡哪个先来。

我们要学会使用工具,而不是把自己变成工具。在工作中,大家要学聪明一点,不要做那些低价值的重复性的工作,也就是说,少做打杂的工作让自己沦为工具人。要想着在工作中,哪些技能是你能带走的,自己能带走的本事才是真的本事。历练自己,就是要挑着那些能带走的技能历练,不要挑那些谁都能干的任务,不要把自己当作一颗螺丝钉。

有人可能会说,这样会不会太自私了?兄弟,我巴不得你们自私一点,你可以为了自己拼命,可以为了家人拼命,唯独不要为资本拼命。某种程度上来说,为资本拼命害人害己。

中国每天都在有造富的神话,让人们都心浮气躁了。其实你看的新闻全都是小概率事件。新闻之所以是新闻,正是因为它不常见所以人们才爱看。你身边整天充斥的消息,并不是这个世界的真相。

有些人不信命,总想带着天涯海角的辽阔期待着一个奇迹。我劝大家不要相信奇迹,相信什么自己是天选之人。我说的命不是指命运,而是指你能力的上限。 我们要做那些大概率成功的事情,而不是去搏一个小概率。中国教育真正牛的地方在于,它能把那些资质平庸的人培养成可用的人才,让那些没有天赋的人也有机会展示自己。

我不是叫你不去努力,努力可以,但要留有退路。不要跟自己较劲,更不要透支自己的一切去赌明天。稳步向前,别急。

珍惜眼前,跟自己和解。

祝福

我祝你2021年一切顺利!新年快乐!

本文同步于公众号【caiyongji】,原文文末有红包🧧现金💰书籍📖赠送。

查看原文

赞 1 收藏 0 评论 0

caiyongji 分享了头条 · 2020-12-25

Matplotlib 是建立在NumPy基础之上的Python绘图库。【圣诞快乐!感谢支持原创!文末有红包🎁🎁🎁】

赞 0 收藏 1 评论 0

caiyongji 发布了文章 · 2020-12-25

前置机器学习(五):30分钟掌握常用Matplotlib用法

Matplotlib 是建立在NumPy基础之上的Python绘图库,是在机器学习中用于数据可视化的工具。

我们在前面的文章讲过NumPy的用法,这里我们就不展开讨论NumPy的相关知识了。
Matplotlib具有很强的工具属性,也就是说它只是为我所用的,我们不必花太多的精力去精进它。我们只需要知道它可以做那些事,可以绘制哪些图形,有一个印象就足够了。我们在实际使用中用什么拿什么,我们用到了自然就熟练了,用不到的功能也就说明它对你没什么用。
这就是按需学习(Learn on Demand) 。这点我在《如何成为十倍速程序员》里提到过类似的理念。

一、Matplotlib常见用法

1. 绘制简单图像

我们以机器学习中最常见的激活函数sigmoid举例,我们来绘制它。

import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-10,10,1000)
y = 1 / (1 + np.exp(-x))
plt.plot(x,y)
plt.show()

其中sigmoid的公式为: $y = f(x) =\frac{1}{1+e^{-x}}$
plot()方法展示变量间的趋势,show()方法展示图像。
我们得到如图所示图像:
image

2. 添加常用元素

我们添加一些参考元素,各函数的解释我在代码中进行了详细的标注。

x = np.linspace(-10,10,1000)

#写入公式
y = 1 / (1 + np.exp(-x))

#x轴范围限制
plt.xlim(-5,5)

#y轴范围限制
plt.ylim(-0.2,1.2)

#x轴添加标签
plt.xlabel("X axis")

#y轴添加标签
plt.ylabel("Y axis")

#标题
plt.title("sigmoid function")

#设置网格,途中红色虚线
plt.grid(linestyle=":", color ="red")

#设置水平参考线
plt.axhline(y=0.5, color="green", linestyle="--", linewidth=2)

#设置垂直参考线
plt.axvline(x=0.0, color="green", linestyle="--", linewidth=2)

#绘制曲线
plt.plot(x,y)

#保存图像
plt.savefig("./sigmoid.png",format='png', dpi=300)

以上代码包含了限制X、Y轴范围,添加标题和标签,设置网格,添加参考线,保存图像等内容。
绘制图像如下:

image

3. 绘制多曲线

#生成均匀分布的1000个数值
x = np.linspace(-10,10,1000)

#写入sigmoid公式
y = 1 / (1 + np.exp(-x))
z = x**2
plt.xlim(-2,2)
plt.ylim(0,1)

#绘制sigmoid
plt.plot(x,y,color='#E0BF1D',linestyle='-', label ="sigmoid")

#绘制y=x*x
plt.plot(x,z,color='purple',linestyle='-.', label = "y=x*x")

#绘制legend,即下图角落的图例
plt.legend(loc="upper left")

#展示
plt.show()

绘制多图像直接调用多个plot()即可。注意:如果不调用legend()方法,不会绘制左上角的legend(图例)。其中color参数支持hex表示。
image

4. 认识figure(画布)

首先我们认识figure(画布),比如legend我们在上文中提到过,是线条标签的展示。grid所圈住的虚线是网格参考线。Title/x axislabel等文本标签。
这张图有助于我们对figure有一个值观的理解。

image

5. 绘制多图像

一个figure是可以对应多个plot的,现在我们试着在一个figure上绘制多图像。

x = np.linspace(-2*np.pi, 2*np.pi, 400)
y = np.sin(x**2)
z = 1 / (1 + np.exp(-x))
a = np.random.randint(0,100,400)
b = np.maximum(x,0.1*x)

#创建两行两列的子图像
fig, ax_list = plt.subplots(nrows=2, ncols=2)

# 'r-'其中r表示color=red,-表示linestyle='-'
ax_list[0][0].plot(x,y,'r-')
ax_list[0][0].title.set_text('sin')

ax_list[0][1].scatter(x,a,s=1)
ax_list[0][1].title.set_text('scatter')

ax_list[1][0].plot(x,b,'b-.')
ax_list[1][0].title.set_text('leaky relu')

ax_list[1][1].plot(x,z,'g')
ax_list[1][1].title.set_text('sigmoid')

#调整子图像的布局
fig.subplots_adjust(wspace=0.9,hspace=0.5)
fig.suptitle("Figure graphs",fontsize=16)

其中,最关键的是subplots方法,生成2行2列的子图像,然后我们调用ax_list中的各绘图方法。
其中'r-''b-.'参数为绘图的缩写写法,本文后续参数缩写段落会单独讲解。

image

6. 绘制常用图

我们常用图来表示数据之间的关系,常见的图包括直方图、柱状图、饼图、散点图等等。

#使绘图支持中文
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
#创建两行两列的子图像
fig, [[ax1,ax2],[ax3,ax4],[ax5,ax6]] = plt.subplots(nrows=3, ncols=2,figsize=(8,8))

#绘制柱状图bar
value = (2, 3, 4, 1, 2)
index = np.arange(5)
ax1.bar(index, value,alpha=0.4, color='b')
ax1.set_xlabel('Group')
ax1.set_ylabel('Scores')
ax1.set_title('柱状图')

#绘制直方图histogram
h = 100 + 15 * np.random.randn(437)
ax2.hist(h, bins=50)
ax2.title.set_text('直方图')

#绘制饼图pie
labels = 'Frogs', 'Cai', 'Yongji', 'Logs'
sizes = [15, 30, 45, 10]
explode = (0, 0.1, 0, 0)
ax3.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',
        shadow=True, startangle=90)
ax3.axis('equal')  # Equal aspect ratio ensures that pie is drawn as a circle.
ax3.title.set_text('饼图')

#绘制棉棒图stem
x = np.linspace(0.5, 2*np.pi, 20)
y = np.random.randn(20)
ax4.stem(x,y, linefmt="-.", markerfmt="o", basefmt='-')
ax4.set_title("棉棒图")

#绘制气泡图scatter
a = np.random.randn(100)
b = np.random.randn(100)
ax5.scatter(a, b, s=np.power(2*a+4*b,2), c=np.random.rand(100), cmap=plt.cm.RdYlBu, marker="o")

#绘制极线图polar
fig.delaxes(ax6)

ax6 = fig.add_subplot(236, projection='polar')
#ax6 = fig.add_subplot(2,3,6, projection='polar')#2行,3列,第6个图
r = np.arange(0, 2, 0.01)
theta = 2 * np.pi * r
ax6.plot(theta, r)
ax6.set_rmax(2)
ax6.set_rticks([0.5, 1, 1.5, 2])  # Less radial ticks
ax6.set_rlabel_position(-22.5)  # Move radial labels away from plotted line
ax6.grid(True)

#调整子图像的布局
fig.subplots_adjust(wspace=1,hspace=1.2)
fig.suptitle("图形绘制",fontsize=16)

绘制图像如下:
image

7. 参数简写

因为matplotlib支持参数的缩写,所以我认为有必要单独拿出来讲一讲各参数缩写的表示。

x = np.linspace(-10,10,20)
y = 1 / (1 + np.exp(-x))
plt.plot(x,y,c='k',ls='-',lw=5, label ="sigmoid", marker="o", ms=15, mfc='r')
plt.legend()

绘制图像如下:
image

7.1 c代表color(颜色)

字符颜色
‘b’blue
‘g’green
‘r’red
‘c’cyan
‘m’magenta
‘y’yellow
‘k’black
‘w’white

7.2 ls代表linestyle(线条样式)

字符描述
'-'solid line style
'--'dashed line style
'-.'dash-dot line style
':'dotted line style
'.'point marker
','pixel marker
'o'circle marker
'v'triangle_down marker
'^'triangle_up marker
'<'triangle_left marker
'>'triangle_right marker
'1'tri_down marker
'2'tri_up marker
'3'tri_left marker
'4'tri_right marker
's'square marker
'p'pentagon marker
'*'star marker
'h'hexagon1 marker
'H'hexagon2 marker
'+'plus marker
'x'x marker
'D'diamond marker
'd'thin_diamond marker
'\'vline marker
'\_'hline marker

7.3 marker(记号样式)

记号样式展示如下:
image

7.4 其他缩写

  1. lw代表linewidth(线条宽度),如:lw=2.5
  2. ms代表markersize(记号尺寸),如:ms=5
  3. mfc代表markerfacecolor(记号颜色),如:mfc='red'

二、Matplotlib进阶用法

1. 添加文本注释

我们可以在画布(figure)上添加文本、箭头等标注,来让图像表述更清晰准确。
我们通过调用annotate方法来绘制注释。

fig, ax = plt.subplots(figsize=(8, 8))

t = np.arange(0.0, 5.0, 0.01)
s = np.cos(2*np.pi*t)

# 绘制一条曲线
line, = ax.plot(t, s)

#添加注释
ax.annotate('figure pixels',
            xy=(10, 10), xycoords='figure pixels')
ax.annotate('figure points',
            xy=(80, 80), xycoords='figure points')
ax.annotate('figure fraction',
            xy=(.025, .975), xycoords='figure fraction',
            horizontalalignment='left', verticalalignment='top',
            fontsize=20)

#第一个箭头
ax.annotate('point offset from data',
            xy=(2, 1), xycoords='data',
            xytext=(-15, 25), textcoords='offset points',
            arrowprops=dict(facecolor='black', shrink=0.05),
            horizontalalignment='right', verticalalignment='bottom')

#第二个箭头
ax.annotate('axes fraction',
            xy=(3, 1), xycoords='data',
            xytext=(0.8, 0.95), textcoords='axes fraction',
            arrowprops=dict(facecolor='black', shrink=0.05),
            horizontalalignment='right', verticalalignment='top')

ax.set(xlim=(-1, 5), ylim=(-3, 5))

绘制图像如下:

image

2. 绘制3D图像

绘制3D图像需要导入Axes3D库。

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np


fig = plt.figure(figsize=(15,15))
ax = fig.gca(projection='3d')

# Make data.
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)

# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)

# Customize the z axis.
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)

其中cmap意为colormap,用来绘制颜色分布、渐变色等。cmap通常配合colorbar使用,来绘制图像的颜色栏。

image

3. 导入图像(加州房价)

引入mpimg库,来导入图像。
我们以美国加州房价数据为例,导入加州房价数据绘制散点图,同时导入加州地图图片,查看地图经纬度对应房价的数据。同时使用颜色栏,绘制热度图像。
代码如下:

import os
import urllib
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

#加州房价数据(大家不用在意域名)
housing = pd.read_csv("http://blog.caiyongji.com/assets/housing.csv")
#加州地图
url = "http://blog.caiyongji.com/assets/california.png"
urllib.request.urlretrieve("http://blog.caiyongji.com/assets/california.png", os.path.join("./", "california.png"))
california_img=mpimg.imread(os.path.join("./", "california.png"))

#根据经纬度绘制房价散点图
ax = housing.plot(kind="scatter", x="longitude", y="latitude", figsize=(10,7),
                       s=housing['population']/100, label="Population",
                       c="median_house_value", cmap=plt.get_cmap("jet"),
                       colorbar=False, alpha=0.4,
                      )
plt.imshow(california_img, extent=[-124.55, -113.80, 32.45, 42.05], alpha=0.5,
           cmap=plt.get_cmap("jet"))
plt.ylabel("Latitude", fontsize=14)
plt.xlabel("Longitude", fontsize=14)

prices = housing["median_house_value"]
tick_values = np.linspace(prices.min(), prices.max(), 11)

#颜色栏,热度地图
cbar = plt.colorbar(ticks=tick_values/prices.max())
cbar.ax.set_yticklabels(["$%dk"%(round(v/1000)) for v in tick_values], fontsize=14)
cbar.set_label('Median House Value', fontsize=16)
v
plt.legend(fontsize=16)

绘制图像如下:
红色昂贵,蓝色便宜,圆圈大小表示人口多少
image

4. 绘制等高线

等高线对于在二维空间内绘制三维图像很有用。

def f(x, y):
    return np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)

x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)

X, Y = np.meshgrid(x, y)
Z = f(X, Y)
plt.contourf(X, Y, Z, 20, cmap='RdGy')
plt.colorbar()

绘制图像如下:
黑色地方是峰,红色地方是谷。

image

绘制动画

绘制动画需要引入animation库,通过调用FuncAnimation方法来实现绘制动画。

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation

fig = plt.figure()
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
line, = ax.plot([], [], lw=2)

# 初始化方法
def init():
    line.set_data([], [])
    return line,

# 数据更新方法,周期性调用
def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    line.set_data(x, y)
    return line,

#绘制动画,frames帧数,interval周期行调用animate方法
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=200, interval=20, blit=True)
anim.save('ccccc.gif', fps=30)

plt.show()

上述代码中anim.save()方法支持保存mp4格式文件。
绘制动图如下:
image

结语

到此,前置机器学习系列就结束了,我们已经为上手机器学习做足了准备。查看完整《前置机器学习系列》请关注公众号【caiyongji】或访问我的个人博客blog.caiyongji.com同步更新。
大家可能发现了,我的教程中偏向实践的方向更多。接下来的机器学习系列教程也会更多的偏向于实际使用,而非理论方向。

对数学畏惧的同学不要慌,跟着我慢慢学就好。

查看原文

赞 0 收藏 0 评论 0

caiyongji 分享了头条 · 2020-12-19

刚刚看了条新闻,像聊家常似的说两句。希望程序员的心脏能永远“跳动”,指尖的“字节”能永远流淌。

赞 0 收藏 0 评论 0

认证与成就

  • 获得 399 次点赞
  • 获得 47 枚徽章 获得 0 枚金徽章, 获得 2 枚银徽章, 获得 45 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2017-05-29
个人主页被 4.3k 人浏览