基于策尔纳 g 先验的线性回归模型选择
线性回归是复杂模型的构建模块,由于其简单性和易解释性而被广泛使用。
通常,线性回归中模型选择的经典方法是选择具有最高 R 的模型,或者通过 Akaike 信息标准在复杂性和拟合优度之间找到正确的平衡。相比之下,在贝叶斯推理中,我们非常依赖于分布,因为我们在进行估计时会得到一个分布。
在本文中,我们将使用策尔纳的 g 先验来执行模型选择。此外,虽然用 R 和 Python 构建 ML 模型并不常见,但我们将利用 R 包bas
和learnbayes
来说明计算。
解开贝叶斯回归模型
在多元线性回归中,我们感兴趣的是通过一组协变量**【x₁】、…来描述一个目标变量 y 的可变性。这些变量中的每一个通常都有不同的贡献,由相对于每一个变量的系数的权重给出【β₁】、 也就是说,
其中α是截距(当协变量为零时 y 的值),我们假设等方差。如果考虑最小二乘方法(经典统计学),人们将通过最大似然估计来估计未知参数 ( α、 βᵢ 、σ ) 的值。然而,贝叶斯方法让你将每一个系数视为随机变量。因此,目标是获得这些系数可能取值的概率模型,其优点是获得我们对这些系数值的不确定性的估计。
为了实现这一点,贝叶斯方法非常灵活。首先,人们对这些值可能是什么设置了一个先验信念,也就是说,在看到数据 y 之前,我们反映了我们对参数值的了解。例如,假设我们对它们一无所知,那么我们可以考虑一个无信息先验
当人们把这个表达式理解为 ( α,β,σ ) 的联合分布与方差**【σ】的倒数成正比时,这叫做 先验分布。 注意,β是一个向量,其分量为β₁,…,βₙ.
然后是,之后是观察数据 y, 我们设定如何描述给定的参数和协变量。因为我们持有线性回归假设
或者给定 x ,α,β,σ,数据似乎符合一个正态分布,均值为α + β x ,方差为σ,这叫做似然。请注意, x 是一个向量,其分量为 x ₁,…, x ₙ.
最后,贝叶斯定理陈述**后验分布与似然性和先验分布的乘积成正比,
了解了这些组件,您可能会注意到选择先验有点主观。出于这个原因,策尔纳介绍了一种评估一个人对先前的选择有多确定的方法。
策尔纳的方法
1986 年,阿诺德·策尔纳提出了一种在回归模型中引入主观信息的简单方法。想法是用户指定β系数的位置,例如,假设β系数都是酉的,
然后,一个人对这个假设的信念将由常数 g 来反映,该常数反映了先验中相对于数据的信息量。因此,为 g 选择一个较小的值,意味着一个人对这个猜想有更强的信念。相反,选择更大的值 g 具有与选择 ( α,β,σ ) 的无信息先验相似的效果,因为随着g 趋于无穷大,其对先验的影响消失,更多细节参见【2】。**
基于策尔纳 g 先验的模型选择
如果我们对响应变量 y 有 n 个预测值,那么就有 2ⁿ个可能的回归模型。泽尔纳的 g 先验可用于在 2ⁿ候选模型中选择最佳模型。
为此,假设模型具有相同的先验概率,即,对于每个模型,我们为β系数分配 0 的先验猜测和相同的 g 值。然后,我们可以通过计算 先验预测分布 (数据 y 在所有可能的参数值上平均的分布)来比较回归模型。
注意,如果这个积分没有封闭形式的或者有几个维度,那么它可能很难计算。一种近似结果的方法是拉普拉斯方法,更多细节参见[6]和[1]的第 8 章。
曾经,我们计算过每个值【p(y)对于每个 m 模型,我们需要一种方法来比较这些模型。例如,当只比较它们中的两个时,我们可以计算它们先前预测密度的比率,
****这就是所谓的**贝叶斯因子。比值越大,模型 j 对模型 k 的支持度越大,你可以在[1]的第八章和[5]的第六章阅读更多关于贝叶斯因子的内容。
由于我们正在比较 2ⁿ模型,我们可以计算每个模型的后验概率,
最后,我们将选择概率最高的模型。在接下来的几节中,我们将借助 R 包BAS
和learnbayes
来看看这个过程。
代码示例
为了运行 R 和 Python,我们将使用 Jupyter 的 Docker imagedata science-notebook。关于使用 Anaconda 的替代方法,请查看这个 Stackoverflow 问题。
在安装 Docker 后,运行你的终端
****docker run -it -p 8888:8888 -p 4040:4040 -v D:/user/your_user_name:/home/jovyan/work jupyter/datascience-notebook****
如果这是第一次运行这个命令,Docker 会自动拉图片 datascience-notebook。注意,应该启用文件共享来挂载一个本地目录作为 Docker 容器的一个卷,更多内容请参见这里的。
在 Jupyter 中,我们将使用 R 包learnbayes
和bas
来计算具有 g 先验的线性回归模型。此外,我们还使用了来自《汽车碰撞事故》的 Kaggle 数据集,这是 seaborn 默认提供的。
按照[1]第 9 章中的例子,我们将使用LearnBayes
包中的函数bayes_model_selection
来计算每个模型的后验概率。
我们的目标变量 y 将是 total “每十亿英里中涉及致命碰撞的驾驶员数量”。为简单起见,我们将前四个变量作为协变量。
在这种情况下,bayes_model_selection
函数非常直观,因为我们只需提供目标变量、协变量和β的先验猜测中的置信值 g 。
请注意,我们选择了值g=100
,因为我们不太确定之前的猜测。考虑到该值越高,估计值就越接近最小二乘估计值,您可以随意使用该值。
通过访问模型上的mod.prob
,我们可以可视化结果。在下面的代码中,我们按照后验概率的较高值进行排序。
从表中我们看到,最可能的模型认为协变量为未 _ 分心和未 _ 先前。还有,贡献最高的个体变量是 no_previous 和*超速。*****
如果有大量的协变量呢?
当处理大量的协变量,也就是大量的模型时,贝叶斯自适应采样算法是一个很好的选择。它的工作原理是对模型进行采样,而不从可能的模型空间中进行替换。为了说明这一点,我们现在考虑数据集中的所有变量,我们有 2⁶可能的模型可供选择。
同样,具有较高后验概率或较高边际可能性的模型是最有可能的,即,具有协变量集酒精、未分心和否先前的模型。
主要发现
总结一下,让我们概括一些重要的发现:
- 在经典统计学中,人们得到点估计,而在贝叶斯统计学中,人们得到参数可能取值的概率分布。
- 先验是信念,可能性是证据,后验是最终的知识。
- 策尔纳的 g 先验反映了一个人对先验信念的信心。
- 当有大量模型可供选择时,可以考虑使用 BAS 算法。
最后,我们已经看到,模型选择的贝叶斯方法与经典方法一样直观且易于实现,同时还能让您更深入地了解模型的内部工作。
有什么问题吗?留下评论。感谢阅读,如果你喜欢这篇文章,请随意分享。
参考
[1]艾伯特,吉姆。贝叶斯计算与 R 第二版。斯普林格,2009 年。
[2]马林,J.M 罗伯特,Ch。回归和变量选择。网址:https://www.ceremade.dauphine.fr/~xian/BCS/Breg.pdf
[3]克莱德,梅里斯;Ghosh,Joyee 里特曼,迈克尔。变量选择和模型平均的贝叶斯自适应抽样。网址:https://home page . div ms . uio wa . edu/~ jghsh/Clyde _ ghosh _ littman _ 2010 _ jcgs . pdf
[4]阿诺德·策尔纳。用 g-先验分布评估先验分布和贝叶斯回归分析。1986
[5]戈什、贾扬塔;德兰帕迪、莫汉;萨曼塔,塔帕斯。贝叶斯分析导论:理论与方法。斯普林格,2006 年。
[6]贝叶斯模型在 R. URL 中的简易拉普拉斯近似:https://www . r-bloggers . com/Easy-la place-approximation-of-Bayesian-models-in-r/
[7] Rpy2 文档。网址:https://rpy2.github.io/doc/latest/html/index.html
[8]机器学习中模型评估和选择的终极指南。Neptune . ai . URL:https://Neptune . ai/blog/the-ultimate-guide-to-evaluation-and-selection-of-models-in-machine-learning
ML 从零开始:带 NumPy 的线性回归模型
在 Unsplash 上由 Ridham Nagralawala 拍摄的照片
线性回归完全指南
在这个项目中,我们将看到如何创建一个使用多元线性回归算法的机器学习模型。
这个项目的主要焦点是解释线性回归是如何工作的,以及如何使用令人敬畏的 NumPy 模块从头开始编写线性回归模型。
当然,您可以使用 scikit-learn 创建一个线性回归模型,只需 3-4 行代码,但实际上,从头开始编写您自己的模型远比依赖一个在您坐着观看时为您做所有事情的库更棒。
不仅如此,编写定制模型意味着您可以完全控制模型做什么,以及模型如何处理您将提供给它的数据。这允许在训练过程中有更大的灵活性,并且您实际上可以调整模型,使其在将来重新训练或生产过程中根据需要更加健壮和响应真实世界的数据。
在这个项目中,我们的模型将被用来预测一辆汽车的 CO₂排放量的基础上,其特点,如发动机的大小,燃料消耗等。
让我们开始做这个项目吧。
进行必要的进口
首先,我们将导入必要的 PyData 模块。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
现在,让我们导入数据集。该数据集包含在加拿大零售的新型轻型汽车的特定车型燃料消耗等级和估计二氧化碳排放量。
df = pd.read_csv("FuelConsumptionCo2.csv")
print(df.head())
这是数据集的链接。在这个项目的最后,我还将分享包含 Jupyter 笔记本和数据集的 Github repo 的链接。
[## 燃料消费 Co2.csv
点击链接下载 csv 文件-drive.google.com](https://drive.google.com/file/d/13UHA0B1velyQh9fk3eBOK4i337J441Ce/view?usp=sharing)
这是它在我的 Jupyter 笔记本上的样子:
Jupyter 笔记本中数据帧的视图
以下是我们数据集中的列。
- 年款,例如 2014 年款
- 制造例如讴歌
- 车型例如 ILX
- 车辆类别例如 SUV
- 发动机尺寸例如 4.7
- 气缸例如 6 个
- 变速器例如 A6
- **城市油耗(升/百公里)**例如 9.9
- **HWY 油耗(升/百公里)**例如 8.9
- **油耗梳(升/百公里)**例如 9.2
- **二氧化碳排放量(克/公里)**例如 182 →低→ 0
数据争论和功能选择
任何数据科学项目中最重要的步骤之一是预处理数据。这包括清理数据、根据需要对一些列进行类型转换、分类变量的转换以及根据项目要求对数据进行标准化/规范化。
对于我们的项目,预处理的第一步是检查我们是否需要对任何特性/目标变量的数据类型进行类型转换。
print(df.dtypes)
我们得到以下输出:
不同列的数据类型
正如我们所看到的,没有必要对任何列进行类型转换。
数据争论过程的第二步是分析这些特性是否需要标准化。为此,让我们看一看数据框架的描述性分析。
print(df.describe())
数据帧的描述性分析
正如我们所看到的,所有潜在的功能在规模上是相同的,所以我们不需要标准化任何功能。
对于这个项目,我们将选择的特征是发动机尺寸、气缸 & 燃料消耗 _ 组合,目标变量是二氧化碳排放量。
df = df[['ENGINESIZE','CYLINDERS','FUELCONSUMPTION_COMB','CO2EMISSIONS']]print(df.head())
我们的下一步——检查数据帧中 NaN(null)值的数量。
for i in df.columns:
print(df[i].isnull().value_counts())
数据帧中的空值计数
正如我们所看到的,在我们的数据帧中没有空值。所以这些数据非常适合训练模型。
数据可视化和分析
首先,我们将看看特征和目标变量的相关性。
print(df.corr())
该表显示了特征和目标变量之间的强正相关性。记住,强相关性对于线性回归模型来说是一件好事。
现在,让我们将不同特征相对于目标变量的曲线可视化。这将使我们了解这些特征是否与目标变量呈线性关系。
fig, a **=** plt.subplots(1,3, figsize **=** (18, 5))a[0].scatter(df['ENGINESIZE'], df['CO2EMISSIONS'], color **=** 'c')
a[0].set_title('Engine Size vs CO2 Emissions')
a[0].set_xlabel('Engine Size (L)')a[1].scatter(df['CYLINDERS'], df['CO2EMISSIONS'], color **=** 'm')
a[1].set_title('No. of Cylinders vs CO2 Emissions')
a[1].set_xlabel('No. of Cylinders')a[2].scatter(df['FUELCONSUMPTION_COMB'], df['CO2EMISSIONS'], color **=** 'b')
a[2].set_title('Fuel Consumption vs CO2 Emissions')
a[2].set_xlabel('Fuel Consumption (L/100km)')fig.text(0.08, 0.5, 'CO2 Emissions', va**=**'center', rotation**=**'vertical') plt.show()
不同特征(x 轴)与目标变量(y 轴)的关系图
正如我们所看到的,这些特征显示了与目标的相当大的线性关系。因此,我们可以用它们来训练模型。
从零开始的线性回归模型
线性回归使用以下数学公式,通过自变量预测因变量。
y = wx + b
这里,
- y -因变量
- x -因变量
- w -与自变量相关的权重
- b -给定 lin-reg 方程的偏差
以下是开发线性回归模型的过程。
- 将数据集分成训练集和测试集。然而,为了简单起见,我们将在自定义模型中跳过这一步。
- 给模型分配随机权重和偏差,然后根据随机权重和偏差计算因变量 ŷ 。
- 使用损失函数来计算总信息损失,即模型内的总不准确性。在我们的例子中,我们将使用均方差(【MSE】)损失函数。
- 我们的下一步是减少我们模型的总均方误差。为此,我们将使用随机梯度下降( SGD *)函数,这是回归模型中最常用的优化算法之一。*我们将在编写优化器函数时详细讨论 SGD 函数。
- 我们将根据优化算法更新模型权重和偏差,然后重新训练模型。这是一个循环的过程,将不断重复,直到我们实现一个信息损失低的最佳模型。
首先,让我们将特性转换成一个 NumPy 数组,特性。
features **=** df[['ENGINESIZE','CYLINDERS','FUELCONSUMPTION_COMB']].to_numpy() *#Converts the dataframe to numpy array*print(features)
用于训练模型的一组特征
现在,让我们将目标列转换为一个 NumPy 数组, target 。
target = df[‘CO2EMISSIONS’].to_numpy() #Converts the dataframe to numpy arrayprint(target)
目标变量数组(车辆的实际 CO₂排放值)
由于我们有 3 个因变量,我们将有 3 个权重。让我们生成 3 个小随机权重的数组权重。
weights **=** np.random.rand(3) *#Generates a numpy array with two small random floats*print(weights)
因为我们只有一个目标变量,所以我们只有一个偏差, b 。我们还将创建一个数组 bias 等于 features 数组的长度,每个元素都有 bias b 。
b **=** np.random.rand(1) *#Generates a numpy array with a small random float*bias **=** np.array([b[0] **for** i **in** range(len(features))])print(bias)
偏置阵列
现在,我们将定义使用权重、偏差和因变量来计算ŷ.的模型函数
**def** linearRegr(features, weights, bias): """Calculates the y_hat predicted values using the given parameters of weights, dependent variables, and biases. Args:
-dependant_var: Matrix of dependant variable values
-weights: Matrix/array of weights associated with each dependant variable
-biases: Biases for the model
Returns:
-Array/matrix of predicted values """ y_hat **=** weights.dot(features.transpose()) **+** np.array([bias[0] **for** i **in** range(len(features))]) *# Takes the value stored in the bias array and makes an array of length of feature matrix for addition* **return** y_hat
现在,让我们运行该函数一次,看看我们将得到的结果。
y_hat = linearRegr(features, weights, b)
print(y_hat)
针对随机生成的权重和偏差运行 linearRegr 函数获得的ŷ(发音为“y_hat”)数组
现在,我们将定义 MSE 函数来计算我们的模型的总损失。
def meanSqrError(y, y_hat):
"""Calculates the total mean squared error.
Args-
y: Array of actual target values
y_hat: Array of predicted target values
Returns-
total mean squared error
"""
MSE = np.sum((y - y_hat) ** 2) / len(y)
return MSE
现在让我们根据之前得到的值来计算信息损失。
print('Total error- {}'.format(meanSqrError(target, y_hat)))
正如我们所看到的,我们的模型目前非常不准确,我们需要优化它。
优化模型
现在是线性回归中最重要的一步。制定 SGD 函数。与到目前为止我们已经讨论过的所有基本函数相比,这是一个稍微高级的主题。需要一些微分学的知识;具体来说是偏导数。我试图在下面的图片中解释这一点,但是,如果你不明白,我强烈建议你在进一步学习之前熟悉机器学习的数学部分(微积分,统计和概率,线性代数)。
图片来源- 阿达什·Menon-Medium.com
一旦我们计算出梯度,我们将按如下方式更新参数。
- m = m - α D m
- c = c - α D c
这里,
- E——总均方误差
- m -与特征相关的权重
- c -模型偏差
- y -实际目标值的数组
- ŷ -预测目标值
- Dm-E w r t 重量的偏导数 m
- Dc-E w r t 偏差的偏导数 c
- α -学习率,即优化器函数采取的步长。
一旦我们有了权重和偏差的新的更新值,我们将再次计算损失。我们将对 n 个时期重复该过程,即循环次数,并在每个时期后绘制损失值。为了保持代码的整洁,我将创建一个单独的函数来计算梯度。
def gradient(target, features, weights, bias):
"""Returns the gradient(slopes) for weights and biases
"""
m = len(features)
target_pred = linearRegr(features, weights, bias)
loss = target - target_pred # y-y_hat
# Gradient calculation for model bias
grad_bias = np.array([-2/m * np.sum(loss)])
grad_weights = np.ones(3)
# Gradient calculation for first feature
feature_0 = np.array([feature[0] for feature in features])
grad_weights[0] = -2/m * np.sum(loss * feature_0)
# Gradient calculation for second feature
feature_1 = np.array([feature[1] for feature in features])
grad_weights[1] = -2/m * np.sum(loss * feature_1)
# Gradient calculation for third feature
feature_2 = np.array([feature[1] for feature in features])
grad_weights[2] = -2/m * np.sum(loss * feature_2)
return grad_bias, grad_weights
现在,让我们编写 SDG 函数,它将返回更新后的权重和偏差,这样我们就可以制定我们的最终模型。
def stochGradDesMODIFIED(learning_rate, epochs, target, features, weights, bias):
"""Performs stochastic gradient descent optimization on the model.
Args-
learning_rate- Size of the step the function will take during optimization
epochs- No. of iterations the function will run for on the model
target- Actual emission values
features- Matrix of dependent variables
weights- Weights associated with each feature
bias- Model bias
Returns-
return_dict = {'weights': weights, 'bias': bias[0], 'MSE': total_MSE_new, 'MSE_list': MSE_list}
"""MSE_list = []
for i in range(epochs):
grad_bias, grad_weights = gradient(target, features, weights, bias)
weights -= grad_weights * learning_rate
bias -= grad_bias * learning_rate
new_pred = linearRegr(features, weights, bias)
total_MSE_new = meanSqrError(target, new_pred)
MSE_list.append(total_MSE_new)
return_dict = {'weights': weights, 'bias': bias[0], 'MSE': total_MSE_new, 'MSE_list': MSE_list}
return return_dict
最后,我们有线性回归模型的优化函数。现在让我们运行该函数,并存储这些值以备将来使用。
model_val = stochGradDesMODIFIED(0.001, 2000, target, features, weights, bias)print("Weights- {}\nBias- {}\nMSE- {}".format(model_val['weights'], model_val['bias'], model_val['MSE']))
更新权重、偏差和 MSE 误差
最初的 MSE 约为 65,000,而目前的 MSE 约为 680。从结果可以看出,我们的模型有了显著的改进。
最后,我们将编写使用更新的模型权重和偏差来预测目标值的模型函数。
def LinearRegressionModel(model_val, feature_list):
"""Predicts the CO2 emission values of the vehicle
Args-
model_val- This is the dictionary returned by the stockGradDesMODIFIED function. Contains model weights and biases
feature_list- An array of the dependent variables
Returns-
co2_emission- Emission predictions for the given set of features
"""
co2_emission = np.sum(model_val['weights'] * feature_list) + model_val['bias']
return co2_emission
测试和评估
作为测试运行,我们现在将在以下数据上测试我们的模型。
feature_list = [2.0,4,8.5]
数据的实际目标值是 196。让我们看看我们的模型进展如何。
target_price = 196
feature_list = [2.0, 4, 8.5]
predicted_price = LinearRegressionModel(model_val, feature_list)
print(predicted_price)
预测的二氧化碳排放量
给定模型的原始目标值是 196。正如我们所看到的,考虑到这是一个从零开始的模型实现,我们的模型在进行预测方面做得相当好。不过,您可以通过调整一些东西或者运行更多的优化时期来进一步改进该模型。然而,过多的优化会导致模型过度拟合,这同样对模型不利,因为过度拟合使得模型实际上不能用于真实世界的数据。
现在,为了检查我们模型的准确性,我们将计算它的 r 平方得分。以下是 r2 得分的公式-
R 平方得分公式
def r2_score(target, prediction):
"""Calculates the r2 score of the model
Args-
target- Actual values of the target variable
prediction- Predicted values, calculated using the model
Returns-
r2- r-squared score of the model
"""
r2 = 1- np.sum((target-prediction)**2)/np.sum((target-target.mean())**2)
return r2
我们模型的 r 平方得分
正如我们所看到的,我们的模型解释了响应数据围绕其平均值的大约 83%的可变性,这是相当好的。然而,机器学习模型总是有改进的空间!
至此,我们的项目告一段落。
我将制作一系列博客,在那里我们将从事类似的项目,从头开始编写新的 ML 模型,用真实世界的数据集和问题陈述进行实践。
我只是机器学习和数据科学领域的新手,所以任何建议和批评都将真正帮助我提高。
点击以下链接,继续关注更多 ML 内容!
数据集和 Jupyter 笔记本的 GitHub repo 链接-
[## aman Sharma 2910/CO2 _ 排放 _ 预测 ML
通过在 GitHub 上创建帐户,为 aman Sharma 2910/CO2 _ emission _ prediction ml 开发做出贡献。
github.com](https://github.com/amansharma2910/CO2_emission_predictionML)
线性回归建模过程
预测金县房地产市场
Sabine Ojeil 在 Unsplash 上拍摄的照片
不久前,我的任务是建立一个可以用来预测连续变量的模型。我们将通过考察华盛顿州的金县来了解这一点——普吉特湾周围和西雅图东部的地区。我们将尝试使用数据集中包含的大量参数来预测价格。这篇文章将是我建模过程的一步一步的指导。我们的流程是:
- 了解数据
- 电子设计自动化(Electronic Design Automation)
- 数据清理
- 特征工程
- 建模
- 结果
了解数据
我们应该做的第一件事是检查数据帧的一部分,它给出了下面的输出。
数据集中包含的原始要素-不包括价格。
从现在开始,我们将把数据帧的列称为“特征”。房屋的特征包括浴室和卧室的数量、房屋占地面积、二楼和地下室(如果适用)的大小、地块的大小以及各种年龄和位置的衡量标准。
查看数据的一个好方法是把它绘制出来。下面是一个国王县的所有房屋的地块。当数据允许的时候,这是获得你的观察的感觉的一个令人惊奇的方法。
空间图形是用高亮显示的代码完成的这里。
探索性数据分析— (EDA)
我们的下一步是深入研究数据——主要是,我们将关注价格的分布,并留意异常值。下面的代码设置了价格的分布,并告知查看者分布的偏斜度和峰度。
不是正态分布
从图中可以看出,分布是不正态的。它聚集在标尺的左端,许多观察发生在远离峰值的地方。我还把曲线的偏斜度和峰度编码进了图中。有关偏斜度和峰度的更多信息,请阅读此处包含的信息。
这个分布不起作用,所以现在我们可以看看正态分布的自然对数形式。
这些观察值呈正态分布,偏度和峰度都在正常范围内。我们将保持价格在日志形式的其余 EDA 的视觉目的。最后,我们将把价格转换回我们结果的原始形式。
接下来,我们对数据中的任何趋势、异常、异常值和可能的错误取一个峰值。这需要关于找房子的领域知识。任何人在查看一栋房子时,都会查看它有多少卧室和浴室,房子的占地面积,以及房子周围有多少土地——所以这是我们要开始的地方。
首先,我们看看卧室。
异常存在于卧室数量的两个极端
马上就能看出数据中有一些异常。我们有很多房子没有便宜的卧室。这违背了房子的主要功能,所以我们必须进一步调查。在另一个极端,我们有一个价格合理的家,有一个数据集导致 33 间卧室。在我们做了更多的 EDA 之后,我们会回来交叉引用这些房子。
接下来,我们去浴室。
反常现象存在于两个极端。
这里同样清楚的是,数据有错误。一栋房子需要一个卫生间才能被认为是可居住的,一个低于 50 万美元的 7.5 卫生间的房子是可疑的。我们将不得不清理条目,但是一个接一个地清理效率太低。我们将在下一节的数据清理中这样做。
数据清理
数据清理可能是我们在建模中最重要的任务——比特征工程更重要。您可以创建所有您想要的功能,编写最复杂的模型,甚至进行所有您可以进行的数据分析——如果您的数据仍然是脏的,这些都没有任何意义。
这并不是说你会得到完全干净的数据。你将不得不做出可能影响某些观点的判断,但重点是用你受过最好教育的猜测来填补空白。
首先,我们试着清理卧室的异常。
使用矢量化技术 np.select() ,我们尝试概括卧室的清理。这是针对零卧室的条目,应该得到更多。
我最终拒绝修理卧室,因为它将基于浴室。输入一次数据是可以接受的,但是用输入的数据来输入数据是一个大禁忌。
特征工程
创建特征将有助于模型确定价格。特性越有价值,模型就越好。我将仔细检查我创建的每个特性——给你每个特性的推理和代码。
首先,我着手确定一个列表是否是一个住所。当我加载上面的数据时,你可以看到其中两个特性是 sqft_living 和 sqft_lot 。这是房子的大小和它所在的土地的大小。
地段的大小使房子的大小相形见绌
在上面的读数中,您可以看到地块大小比房屋大得多——这是意料之中的,但没有一个顶级地块大小被列为顶级房屋大小。所以我们进一步调查。
现在,我们把居住空间和地段大小做一个比例。
一个简单的比率来更好地理解
我只是使用了。head()方法来调用下面的读数。正如你所看到的,有些房产的比率非常小——这意味着与房子的大小相比,他们有很多土地。
接下来,我们继续讨论房子的年龄。大多数房屋的翻修率为零。我认为这意味着它们从未翻修过。其余的都是一年期的。所以我想弄清楚这栋房子现在的布局有多古老,有一个古老的特征。
使用上面的代码,很容易看出,对于任何翻新的房子,我都从数据收集的年份中减去该年( 2015 )。如果它从未翻修过,我就从收集数据的年份中减去它建造的年份。
最后,我很早就注意到有些观察根本不是家。那里有谷仓、公寓楼,甚至还有一个小型机场。所以,后来我决定创建一个名为 residence 的二元特征。
这给了所有我认为应该被归类为单一家庭住宅的房子一个值——所有其他的都给了零个值。
领域知识
任何数据科学项目的一个重要方面是给定主题的领域知识。领域知识是关于你正在探索的主题的信息量。在这种情况下,领域知识将包括关于房屋市场、西雅图及其周边郊区以及华盛顿州中部的信息。
我使用的一个方面是我对西雅图市区的领域知识。使用派克市场作为西雅图市中心的中心点,我计算了从每个观察点到派克市场的距离。我从未说过我的领域知识包罗万象。
geopy 包附带了一个叫做测地线的方便的子包。众所周知,使用坐标来确定距离是很棘手的,因为我们生活在一个半球上。这意味着越靠近赤道,经度线之间的距离就越大。然而,这个软件包考虑到了这一点,并提供了两点之间的距离。
在上面的代码中,为了运行测地线函数,我使用了纬度和经度的元组。我选择公里是因为我更喜欢国际单位制,但这是你可以选择的。在我们有了到 Pike Place Market 的距离的新列之后,我们从该列中去掉了 km ,并将其更改为 float,这样它就可以在模型中使用了。
建模
让我们进入项目的建模阶段。我们的衡量标准是均方根误差(RMSE)。想了解更多关于 RMSE 的信息,请看这里。首先,我们必须加载所有的包。
然后,我们将数据分为特征和目标。
现在,我们准备运行一些模型。我选择为这个项目运行三个模型:
线性回归旨在最小化数据集中观察到的目标与通过线性近似预测的目标之间的残差平方和。
ElasticNetCV 是一种沿着正则化路径通过迭代拟合查看数据的模型。然后通过交叉验证选择最佳模型。
梯度推进回归器是一种用于回归和分类问题的机器学习技术,它以弱预测模型(通常是决策树)的集合的形式产生预测模型。
引入多项式是为了看看特征的组合是否有助于建模。
结果
一些模型比其他模型做得更好。总的来说,多项式数据帧的表现比普通数据帧差。
对于线性回归,多项式数据框架在测试数据上运行时经历了我只能描述为致命的故障——除了 ElasticNetCV 的情况。这是训练模型和测试模型之间最一致的分数。
然而,在我们所遵循的指标上做得最好的模型是在正常数据框架上工作的梯度推进回归器。使用 3000 个估计量,该模型能够在测试数据上降低 RMSE。但有趣的是,训练数据的 RMSE 要低得多,这表明该模型对于训练数据来说是过拟合的。
如果你想多谈谈这个,你可以在 LinkedIn 上联系我。
或者如果你想在 Github 上看到这个回购,点击这个链接。
链接:
- 看看这个方便的包: Geopy
- 如果你想浏览地图,请阅读下面的文章。
将您的数据带入现实世界
towardsdatascience.com](/using-geopandas-for-spatial-visualization-21e78984dc37)
线性回归还是广义线性模型?
为机器学习应用选择正确的算法
在机器学习中,应用线性回归来预测结果(称为因变量),作为一个或多个与结果相关的预测因子(称为自变量)的函数。例如,班级学生的体重可以用两个变量来预测——年龄、身高——这两个变量与体重相关。在线性函数中,这种关系可以表示为:
体重= c+B1 *年龄+B2 *身高
c、b1、b2 是从训练数据中估计的参数。
在这种回归中,有两个重要的假设:a)结果是一个连续变量,b)它是正态分布的。
然而,现实中并非一直如此。结果并不总是正态分布,也不总是连续变量。
以下是违反这些假设的许多例子中的几个:
- 结果变量是二元的,有两类;在泰坦尼克号灾难中幸存/未幸存
- 结果是一个分类变量,多类;例如通过卫星图像预测的土地覆盖类别
- 结果是计数数据;例如每年的交通事故数量
- 结果是一个连续变量,但有偏差,不是正态分布;美国的收入分配向右倾斜
既然普通的线性回归不适合这些情况,那么有什么替代方法呢?以下是一些选项:
在上述#1 和#2 的情况下,如果结果/因变量是二元或分类的,机器学习分类模型应该工作良好。L 针对二元的逻辑回归和针对多类分类的随机森林是机器学习领域中两种常用的算法。
这给我们留下了以下两种情况,普通的线性回归和分类算法都不起作用:
1)计数结果
2)持续但有偏差的结果
这就是广义线性模型(GLM)派上用场的地方(旁白:它是广义线性模型,而不是广义线性模型,广义线性模型是指传统的 OLS 回归)。glm 是一类模型,适用于线性回归不适用或无法做出适当预测的情况。
GLM 由三部分组成:
- 随机分量:概率分布的指数族:
- 系统成分:线性预测器:和
- 链接函数:推广线性回归。
R 和 Python 中有几个很棒的包可以实现 GLM,但下面是一个使用 Python 中的statmodels
库的实现。
GLM 模型输出
注意,如果你对 R 编程语言感兴趣,一定要看看这个来自普林斯顿大学研究员 T2 的例子。
摘要
总之,在本文中,我们已经讨论了如果结果是一个连续变量并且是正态分布,则应用普通线性回归。然而,也有这两个假设不成立的情况。在这些情况下,应用一套广义线性模型。GLM 有三个要素:随机、系统和链接功能,需要在每个模型实现中指定。
希望这是有用的,你可以关注我的 Twitter 更新和新文章提醒。
了解斜率敏感性的线性回归模拟
您的回归输出如何因样本而异
介绍
在接下来的几分钟里,我将带你走上利用线性回归的道路,而不仅仅是解释或预测,而是为了推断而利用它们。
我们将以三种方式利用模拟进行推理:
- 了解模型敏感度
- p 值
- 置信区间
在本帖中,我们将主要探讨第一个问题。这将是我下一篇使用模拟来确定 p 值和置信区间的基础。
传统回归
如果你不熟悉线性回归一般是如何工作的,请跳到这篇文章。
你可以跳过这里找到关于线性回归不同变化的各种帖子,从创建它们,到理解和解释它们。
增强信心
传统上,我们使用线性回归对各种变量进行评估。除了评估之外,我们在这里要学习的是如何调整各种回归模型的输入,以加深对解释变量和响应变量之间关系的敏感性或可变性的理解。
那么,我们如何确定两个变量之间关系的可变性呢?
这样想吧…
线性回归的关键输出是什么?如果你猜对了一行,那你就猜对了!回归输出实际上是一条直线的方程,该方程的斜率作为X
& Y
关系的指示。在寻求理解我们的变异反应时&解释变量之间的关系…我们要找的是斜坡。假设您对不同的样本进行了线性回归…我们的问题是,我们的斜率会变化吗?或者变化有多大?是不是有时积极,有时消极?等等。
我们追求的笑点
我们已经做了一些解释,以达到这里的妙处,但希望这能给你一个坚实的基础,真正理解和使用这是实践。
总结我们的介绍,它归结为这一点:
当我们改变样本 驱动模型时,我们希望了解两个变量之间关系的可变性和对可变性的敏感性
让我们得到我们的第一个斜坡!
我们正在处理的数据集是西雅图房价数据集。我以前多次使用过这个数据集,发现它在演示时特别灵活。数据集的记录级别是按房屋和详细价格、平方英尺数、床位数、浴室数等。
在这篇文章中,我们将尝试通过其他平方英尺的函数来解释价格。
在进入这一部分之前,肯定有很多探索性的数据分析工作需要你去做。您还需要确认某些数据先决条件,但是为了便于说明,让我们深入了解一下。
fit <- lm(price_log ~ sqft_living_log
data = housing)
summary(fit)
完美!我们已经有了一个线性模型,让我们来想象一下。还要记住,我已经记录了两个变量的日志,以清理和标准化它们的分布。
housing %>%
mutate(sqft_living_log = log(sqft_living),
price_log = log(price))%>%
ggplot(aes(x = sqft_living_log, y = price_log)) +
geom_point() +
geom_smooth(method = "lm", se = FALSE)
在这个数据集中,我们只是处理了 4600 个家庭的样本。这不是一个详尽的群体。因此,我们将使用某种采样技术来生成许多“视角”。上述观点将推动我们如何理解我们的反应和解释变量的敏感性。
当试图对潜在人群得出结论时,抽样可变性造成了困难。我们所拥有的这些多角度的数据或样本是我们如何消除抽样可变性的潜在不利影响的。
所以上面我们有一行……但是我们需要的是许多行,用于许多情况。
我们下一步要做的是在更小的组中抽样我们的住房数据,给每个组一个回归模型。
首先,我们将使用rep_sample_n
函数随机选择一组 100 个家庭…我们将重复这个过程总共 100 次。
samples <- housing %>%
rep_sample_n(size = 100, reps = 100)
现在我们已经有了样本数据集,让我们像以前一样可视化它们。只有在这种情况下,我们将通过复制对我们的可视化进行分组。这一点之所以相关,是因为我们可以点对点地进行区分;它们属于哪个副本。正如您在上面的代码中看到的,将有 100 个记录的 100 个副本。
ggplot(samples, aes(x = sqft_living_log, y = price_log, group = replicate)) +
geom_point() +
geom_smooth(method = 'lm', se = FALSE)
你将在上面看到的是适合 100 个不同样本的各种回归线。如你所见,有些情况下斜率更大或更小。这是我们能够理解适用于底层人群的“斜率”范围的基础。
正如你所想象的,与我们的样本互动会改变斜率的变化量。下面我运行了相同的代码,但是每次复制只抽取 10 个随机样本。
这里你有可视化,但是你还没有线性回归本身的实际细节。
我们需要为每个复制运行一个单独的回归。
由于我们已经生成了模拟数据集,我们只需要通过复制进行分组,在这种情况下,这不是为了聚合,而是为了在组级别建模。一旦我们声明了我们的group_by
,我们将利用do
函数来指示我们的组动作。对于群体行动,我们希望为他们每个人运行单独的模型。
现在我们有 100 个回归输出。
虽然输出中有许多相关部分,但我们将术语作为解释变量。
看看下面的代码吧!
coefs <- samples %>%
group_by(replicate) %>%
do(lm(price_log ~ sqft_living_log, data = .) %>%
tidy()) %>%
filter(term == 'sqft_living_log')
现在,我们有了一个数据框架,其中包含了我们感兴趣的项的每个重复和相应的系数。
让我们来看看我们的斜坡分布。
ggplot(coefs, aes(x = estimate)) +
geom_histogram()
我们可以看到一个正态分布。在我们用更多的重复运行它的情况下,它看起来会更平滑。
你要记住一件事。我并不是说每次运行线性回归时,你都需要对不同的数据样本任意运行 100 次。对于许多业务应用程序,您的数据可能代表整个群体。但是即使在没有全部人口的情况下,这两种方法的目的也是不同的。在这里,我们利用模拟和许多线性回归模型,最终对潜在人群做出推断。对于像解释/描述建模或预测这样的事情,利用不同格式的线性回归仍然是有意义的。
斜率的变化
当我们试图理解斜率系数的分布时,改变最终支持所述分布的数据会非常有帮助。如上所示,改变每个重复的样本大小将有助于更好地理解不同样本斜率变化的减少。
另一个导致斜率变化更大的因素是解释变量变化的减少。这可能有点令人惊讶,但由于解释性数据点的范围更广,我们的模型有更多的信息来解释关系。
结论
我们在这么短的时间内做了很多事情。在剖析推断这样的统计学概念时,很容易迷失。我希望对模拟的需求和相应的执行有一个很强的基础理解,以便更好地理解我们的反应和解释变量之间的关系。
如果这有帮助,请随时查看我在 datasciencelessons.com的其他帖子。祝数据科学快乐!
线性回归:(实际上)完全介绍
一位同学用 Python 对这个简单的机器学习算法进行了全面、深入的解释
Python 线性回归代码(所有照片由作者提供)
I 简介
我记得我第一次钻研机器学习领域时是多么兴奋。炒作是可以理解的,有哪个软件工程专业的学生不想投身到当今最激动人心的相关技术中呢?
但是随着我兴趣的增长,我开始在这个问题上自学,我经常被我读到的一些文章的技术性吓到。精彩的文章,毫无疑问,但写得太超前了,即使是那些针对初学者的文章。另一方面,许多人过于务实,忽略了理论解释,而倾向于让新的学习者尽快上手。虽然两者都很有价值,但我觉得,作为一名学生,我可以在这里填补一个空白。
我的目标是整合我希望在开始时就能掌握的所有信息,概述这个简单的机器学习算法背后的理论,然后以一种可理解但全面的方式给出一个解释透彻的实际例子。 一个学生对另一个学生。
因此,欢迎阅读我希望在构建第一个线性回归模型时能够读到的文章。
一些理论
R 回归分析是一套统计过程,我们通过它来估计一个或多个给定自变量*【x】的因变量【y】*之间的关系。在机器学习的背景下,它是监督学习的一个子领域。
回归有几种类型,每一种描述自变量和因变量之间不同的数学关系。一些常见的例子包括多项式,逻辑和,本文的主题,线性。
一名学生对 Python 中机器学习算法背后的理论和应用的深入探究
towardsdatascience.com](/polynomial-regression-the-only-introduction-youll-need-49a6fb2b86de)
但是你如何选择呢?有什么区别?嗯,就像我上面说的,要看数据。举个例子:比方说,我们希望预测一种疾病在人群中蔓延并逐渐消失的过程。自然地,随着天数的增加,病例数也会增加——直到它们开始下降,形成抛物线形状。如下图所示,最佳拟合直线无法准确预测第 100 天的病例数。但是多项式回归可以。但是我们将在下一篇文章中深入探讨这个问题。
线性回归不适用的例子
相反,当我们有如下图所示的趋势变化的数据时,一条直线就相当准确。这是一个线性回归:
线性回归适用的例子
因此,当因变量和自变量之间的关系可以相当准确地建模为直线时,就使用线性回归。
这将是我们的*最佳拟合线,*你可能还记得高中时的等式:
The way I learnt it in high school: y = mx + c
Machine Learning convention: h(X) = W0 + W1.X
其中:
- y 或 h(x) =因变量(也就是我们试图估计的)
- m 或 W1 =坡度
- x 或 X =因变量(又名输入值)
- c 或W0= y 轴上的截距
术语
我们如何找到最佳拟合直线的方程?通过调整一组参数(W0 和 W1)直到我们找到它们各自的值,使得模型的残差平方和(实际值和预测值之间的差)尽可能小。
线性回归的一些残差
在继续之前,让我们复习一些重要的术语。很容易混淆这些术语,但是理解这些指标对于确定模型的可靠性至关重要。
差异
本质上,方差是对我们的最佳拟合线有多不准确的一种度量,并通过 R 分数来量化。我们的目标是使方差尽可能小,所以我们的 R 得分越高越好。
稀有
有时称为成本函数,用于将方差表示为预测的决定系数 R ,其范围从 0 到 1,1 为最佳拟合。
均方误差
误差平方的平均值(我们将它们平方,因此没有负值)。数字越大,误差越大。我们的目标是尽量减少这种情况。
该算法
我们将使用 普通最小二乘法 方法,这是一种简单的解析的非迭代解法。如果我们想要应用更复杂的机器学习算法,比如支持向量机,那么我们需要使用 梯度下降,,这将给我们一个迭代完成的 OLS 解的近似值。但是这是另一篇文章的主题。
因此,使用上述函数,我们训练我们的模型,直到它学习到最小化残差平方和的最佳系数。一旦我们在一些数据(比如说,数据集的前 80%)上训练了我们的模型,我们将在其余的数据(另外的 20%)上测试它。
这个例子
让我们从头开始,进口:
- matplotlib(py plot & RC params)——创建我们的数据可视化
- sci kit-Learn(load _ diabetes & linear _ model)—执行机器学习
- NumPy——做科学计算
import matplotlib.pyplot as plt
from matplotlib import rcParams
from sklearn.datasets import load_diabetes
from sklearn import linear_model
import numpy as np
接下来,我们加载数据集并创建一个对象 *dx。*糖尿病数据集来自 Scikit-Learn,由 10 个生理变量(年龄、性别、体重、血压等)组成。)和一年后疾病进展的指标。目标是从生理变量预测疾病进展。
现在,Scikit-Learn 数据集返回一个叫做 Bunch 的东西,它类似于一个字典。这一堆有各种属性,其中之一是数据。这是我们希望使用的数据矩阵。另一个是目标,我们很快就会谈到。但是我们不需要所有的数据,所以我们选择我们想要的特性,并使用 numpy.newaxis 将数组维数从 1 增加到 2。我们现在已经把数组变成了一个列向量。
d = load_diabetes()
dx = d.data[:, np.newaxis, 2]
如果这一步有点混乱,没关系。重点是,我们现在有了一个包含数据的 2D 数组,这是必要的格式。您真的可以用任何数据集(自定义列表或. csv 文件)来实现这一点,其中您有带有 x 和 y 值的数据点。所以现在我们的看起来像这样:
[[ 0.06169621]
[-0.05147406]
[ 0.04445121]
[-0.01159501]
[-0.03638469]
[-0.04069594]
[-0.04716281]
[... ]]
接下来,我们将数据集分成训练集和测试集——这是机器学习的基本部分。你会注意到。我前面提到的目标属性。这些基本上是正确的值,或响应变量。
dx_train = dx[:-20]
dy_train = d.target[:-20]
dx_test = dx[-20:]
dy_test = d.target[-20:]
此时,散点图会有所帮助。仅仅通过观察,我们就可以推断出线性回归是否会提供一个准确的模型。我将使用 rcParams 添加一些样式,使它看起来更有吸引力,但不要担心这一点。
rcParams['axes.spines.top'] = False
rcParams['axes.spines.right'] = False
rcParams['lines.linewidth'] = 2plt.scatter(dx_train, dy_train, c='#9dd4a7', label='Training data')
plt.scatter(dx_test, dy_test, c='#d66565', label='Testing data')plt.legend(loc="upper left")
散点图上我们的训练和测试数据
你可能知道,看起来好像一条直线可以或多或少地预测这一趋势的走向。
现在有趣的部分来了。我们将为线性回归创建一个对象 lr ,并将数据拟合到其中。
lr = linear_model.LinearRegression()
lr.fit(dx_train, dy_train)
我们剩下要做的就是在散点图上绘制最佳拟合线:
plt.plot(dx_test, lr.predict(dx_test), c='#404040', label='Line of best fit')
我们的最佳拟合和测试数据系列
**恭喜你!**您已经成功训练并测试了一个线性回归模型。
但是我们现在还不能沾沾自喜…
潜得更深
在这个阶段,我觉得我们应该更深入。我们必须了解到底发生了什么。
LinearRegression()类是好事发生的地方。这就是线性模型 lr 适合最小化预测值和目标值之间的残差平方和的系数的地方,正如我前面提到的。
这个类包含了*。fit()* 函数,我们可以看到它被应用于线性回归对象 lr 。我们将训练数据(x 和 y 值)作为参数传入,函数返回对象的一个实例,现在该实例已与数据相匹配。
最后,我们看到。 *predict(),*linear regression()类的另一个函数。这是通过计算最佳拟合直线的方程返回预测值的函数。
理解这些函数的最好方法是重写没有它们的程序。
这是普通最小二乘算法的起点。我们需要做的第一件事是找到最佳拟合线*的梯度 m 和 y 轴截距 c 。*以下是各自的公式:
- m=(μ(x)μ(y)—μ(xy)/((μ(x))2μ(x2))
- c=μ(y)—*m**μ(x)
我们用 numpy.mean 来求平均值 μ 。我将这两个公式实现为一个函数:
def find_gradient_and_y_intercept(): m = (np.mean(dx_train) * np.mean(dy_train)
- np.mean(dx_train * dy_train)) / ((np.mean(dx_train)) **
2 - np.mean(dx_train ** 2)) c = np.mean(dy_train) - m * np.mean(dx_train) return m, c
请注意,现在我们不必像以前一样将数组更改为 2D,因为我们没有使用。 fit() 功能了。因此,将我们之前使用 numpy.newaxis 的那一行修改成这样:
dx = d.data[:, 2]
现在,当我们绘制最佳拟合线时,不使用。 predict() 函数,我们实际上输入了我们对于最佳拟合线的方程, *mx + c,*作为 y 值。
plt.plot(dx_test, ((m * dx_test) + b), c='0.2', label="Line of Best Fit")
一条与之前完全相同的最佳拟合线
**这次真的恭喜你了!**你刚刚从零开始写了一个线性回归算法。希望您现在已经对算法及其相关功能有了透彻的理解。
作为奖励,让我们计算我们模型的均方误差和得分(前面定义的预测的决定系数 R、)。
使用 LinearRegression()类:
mse = np.mean((lr.predict(dx_test)-dy_test)**2)
score = lr.score(dx_test, dy_test)
不使用类:系数 R 定义为 (1 — u/v) ,其中 u 为残差平方和 ((y_true — y_pred) ** 2)。sum() 和 v 是平方和的总和 ((y_true — y_true.mean()) ** 2)。sum():
mse = np.mean((((m * dx_test) + b) - dy_test) ** 2)
score = (1 - ((dy_test - ((m * dx_test) + b)) ** 2).sum() / ((dy_test - dy_test.mean()) ** 2).sum())
答案得出 mse = 2548.07 和 R = 0.47。
结论
这就是对机器学习最简单的算法——线性回归的全面介绍。我希望,作为一名学生,我能够以一种相关和全面的方式解释这些概念。
简单回顾一下我们讲过的内容:
- 线性回归的定义
- 一些重要术语
- 对算法的解释
- Python 中的一个实际例子
- 对示例中函数的详细检查
如果您觉得这篇文章有帮助,我很乐意与您合作!关注我 Instagram 了解更多机器学习、软件工程和创业内容。
编码快乐!
订阅 📚为了不错过我的一篇新文章,如果你还不是中等会员, 加入 🚀去读我所有的,还有成千上万的其他故事!
资源
Scikit 学习 线性 _ 模型。LinearRegression()文档:https://sci kit-learn . org/stable/modules/generated/sk learn . linear _ model。linear regression . html # sk learn . linear _ model。线性回归.预测
Scikit Learn 线性回归示例:https://Scikit-Learn . org/stable/auto _ examples/Linear _ model/plot _ ols . html
sci kit Learnload _ diabetes 文档:https://sci kit-Learn . org/stable/modules/generated/sk Learn . datasets . load _ diabetes . html # sk Learn . datasets . load _ diabetes
Scikit Learn 机器学习简介:https://Scikit-Learn . org/stable/tutorial/basic/tutorial . html
真实 Python 线性回归:https://Real Python . com/Linear-Regression-in-Python/# simple-Linear-Regression
Statisticsbyjim 解读 R:https://Statisticsbyjim . com/regression/interpret-R-squared-regression/
BMC 均方差&R:https://www . BMC . com/blogs/Mean-squared-error-R2-and-variance-in-regression-analysis/
引擎盖下——线性回归
这是一系列文章中的第一篇,在这一系列文章中,我们将使用各种 ML 算法的基本数学方程来理解它们的“幕后”工作。
有这么多优化的实现,我们有时太关注库和它提供的抽象,而太少关注进入模型的底层计算。理解这些计算往往是一个好模型和一个伟大模型的区别。
在本系列中,我将重点放在手工实现算法上,以理解其背后的数学原理,这将有望帮助我们训练和部署更好的模型。
注意——本系列假设您了解机器学习的基础知识以及我们为什么需要它。如果没有,请阅读这篇文章,以了解我们为什么以及如何利用 ML。
线性回归
线性回归是机器学习的支柱,它基于简单的曲线拟合概念
曲线拟合是构建一条曲线或数学函数的过程,该曲线或数学函数与一系列数据点最佳拟合,可能受到约束。
本质上,“模型”产生了一个将输入特征(X)与目标变量(Y)联系起来的线性方程。
考虑以下具有两个输入变量— X1、X2 和一个目标变量 Y 的数据。
包含 5 行的示例数据
线性回归将试图找到 w1、w2 和 b 的最佳值,这样对于每一行数据—
这里, w1 和 w2 是输入变量的系数,而 b 是偏置项。这被称为数据的“最佳拟合线”,算法使用以下步骤反复尝试找到最佳拟合线—
- 给参数 w1 、 w2 和 b 分配随机值。
- 在数据中选取一个实例并计算
3.计算损失——我们的产量与实际产量相差多少?
4.计算 w1 、 w2 和 b 的梯度—我们应该如何改变权重以更接近实际输出?
5.更新 w1 、 w2 和 b 。
6.重复步骤 2–5,直到收敛。
以下一组图像传达了单个变量的步骤—
0.从一组 n 个变量开始
1.给参数分配随机值并绘制假设曲线
2.使用一个数据实例计算ŷ
3.计算损失
4 & 5.计算损失并更新参数
6.对另一个数据实例重复步骤 2–5
1。将随机值分配给 w1 ,w2 和 b
让我们从我们的假设开始——
2.从数据中选择一个实例并计算ŷ
让我们从数据的第一行开始
输入我们假设的参数值,我们计算一个估计的输出
我们的目标是更新参数,使我们的估计输出(ŷ)等于实际输出(y)。
3.计算损失——计算的产量与实际产量相差多少?
这就是事情变得有趣的地方。
我们计算我们的假设离实际值有多远,并更新我们的参数以更接近实际输出。
为了使用梯度来计算和更新我们的参数假设,我们需要使用可微分的函数来计算损失。
我们将使用平方误差作为损失函数。它衡量的是我们的假设(ŷ)和实际产出(y)之间的平方差。平方误差具有独特的优势,因为它确保了微小误差变化的小值,但当模型假设与实际值相差甚远时,误差就会爆炸。
“为什么”此损失值对算法至关重要,将在下一步中清除。
让我们根据我们的假设来计算损失—
4.计算梯度
这是算法中最重要的一步,因为这是我们迭代学习和改进假设以接近实际输出的地方。
我们首先把我们的损失写成模型参数的函数—
为了确定如何改变参数以更接近实际输出,我们计算了每个系数的梯度(偏导数)和偏置项与损耗的关系
这为我们提供了梯度,它测量每个参数对预测输出的影响,本质上告诉我们需要改变每个参数多少才能更接近实际输出。
5.更新 w1 、 w2 和b
哇!看起来我们的假设差了一大截!
这看起来不对。让我们使用一个缩放变量来缩放我们的更新— 学习率(η) 。学习率确保我们的权重不会在每次更新时发生巨大的变化(并开始波动)。
考虑到η= 0.01,我们的更新看起来更合理——
那看起来更合理。
这完成了算法的一次迭代。现在我们重复这些步骤,直到收敛 ,即,直到我们的权重变化不大和/或我们的损失接近于 0。
让我们用更新后的参数对其他数据行进行另一次迭代。
将相同的过程再重复几次*,从前四行数据中随机取样一行(我们保留最后一行来验证我们的模型),我们得到以下参数值—
使用这些,让我们看看验证样本(最后一行)上的错误是什么样子的。
我们的损失几乎为 0。我们可以说模型已经找到了这个数据的最佳参数。
仅此而已。本质上,这就是线性回归的作用。
这真的是线性回归的全部功能吗?
“引擎盖下”是本系列的焦点,我们看了一下线性回归的基础(更具体地说——随机梯度下降),一次取一个样本,并更新我们的参数以适应数据。
虽然这确实是线性回归的核心,但是创建一个好的线性回归模型还有很多工作要做,比如—
1.正规化——L1 和 L2
2.学习率调度
3.正态方程
4.随机与小批量与批量梯度下降
5.提前停止
我将在一个平行系列中讨论这些概念,重点是算法之间的公共优化点。
下一步是什么?
在本系列的下一篇文章中,我们将挑选一个二进制分类数据,并深入了解 逻辑回归 算法。它与线性回归并没有太大的不同,但是它有一些自己的怪癖,需要在线性回归之外提及。
- 经过 15 次迭代,这是我们的损失、梯度和参数值的变化方式—
15 次迭代后的参数更新
线性回归与神经网络
了解模型假设和输出的差异
人工智能的世界既令人兴奋,也让人误解。像“机器学习”和“人工智能”这样的热门词汇最终不仅扭曲了对其能力的一般理解,还扭曲了其功能与其他模型之间的关键差异。在本文中,我想讨论线性回归模型和标准前馈神经网络之间的主要区别。为此,我将对每个模型使用相同的数据集(可以在这里找到:【https://archive.ics.uci.edu/ml/datasets/Energy+efficiency】T4),并比较 Python 中架构和结果的差异。
探索性数据分析
我们正在看 UCI 的能源效率数据集。在数据的上下文中,我们对每个列的定义如下:
- X1 —相对紧密度
- X2 —表面积
- X3 —墙区
- X4 —屋顶区域
- X5 —总高度
- X6 —方向
- X7 —玻璃区域
- X8 —玻璃面积分布
- y1 —加热负荷
- y2 —冷负荷
我们的目标是基于 X1-X8 预测热负荷和冷负荷。
让我们看看 Python 中的数据集…
下面是结果输出
X1 X2 X3 X4 X5 X6 X7 X8 Y1 Y2
0 0.98 514.5 294.0 110.25 7.0 2 0.0 0 15.55 21.33
1 0.98 514.5 294.0 110.25 7.0 3 0.0 0 15.55 21.33
2 0.98 514.5 294.0 110.25 7.0 4 0.0 0 15.55 21.33
3 0.98 514.5 294.0 110.25 7.0 5 0.0 0 15.55 21.33
4 0.90 563.5 318.5 122.50 7.0 2 0.0 0 20.84 28.28
现在,让我们将这些变量中的每一个相对于另一个绘制出来,以更好地了解我们的数据中发生了什么…
在上面的情节中发生了很多事情,所以让我们一步一步地分解它。最初,当绘制这些数据时,我寻找线性关系并考虑降维。主要是多重共线性的问题,它会夸大我们模型的可解释性,损害它的整体稳健性。
在上面的数据中立即突出的是两个因变量之间的强正线性关系和相对紧密度与表面积之间的强负线性关系(如果你仔细想想,这是有意义的)。
维数/特征缩减超出了本文的目的和范围,但是我觉得还是值得一提。
接下来,让我们创建一个关联热图,这样我们可以获得更多的洞察力…
为什么这很重要?我们绘制的关联热图让我们能够立即了解每个特性的数据中是否存在线性关系。显然,随着特性数量的急剧增加,这个过程必须自动化——但这也超出了本文的范围。通过了解我们的数据中是否存在强线性关系,我们可以采取适当的步骤来组合特征、减少维度并选择适当的模型。回想一下,线性回归模型基于线性关系假设运行,其中神经网络可以识别非线性关系。
线性与非线性关系
当我说模型可以识别数据中的线性和非线性(分别在线性回归和神经网络的情况下)关系时,我的意思是什么?下图给出了三个例子:正线性关系、负线性关系和非线性关系。
这就是我们进行初始数据分析(配对图、热图等)的原因,这样我们就可以根据具体情况确定最合适的模型。如果有一个单一的答案和一个普遍的主导模型,我们就不需要数据科学家、机器学习工程师或人工智能研究人员。
线性回归
在我们的回归模型中,我们对每个观测值中的每个特征进行加权,并确定相对于观测输出的误差。让我们用 Python 构建一个线性回归,看看这个特定数据集中的结果。
r_sq = 0.9028334357025505
我们的模型可以解释大约 90%的变化——考虑到我们没有对数据集做任何事情,这已经很不错了。
为了比较这两个模型,我们将着眼于均方差…
r_sq = 0.9028334357025505
mse = 9.331137808925114
神经网络
现在让我们用一个简单的顺序神经网络做完全相同的事情。序列神经网络是矩阵运算的线性组合序列。然而,存在激活函数形式的非线性组件,其允许识别非线性关系。对于这个例子,我们将使用 ReLU 作为我们的激活函数。具有讽刺意味的是,这是一个线性函数,因为我们还没有规范化或标准化我们的数据。(同样,这是另一个必须根据我们的数据逐案选择的组件。)
Epoch 1000/100032/768 [>.............................] - ETA: 0s - loss: 5.8660 - mse: 5.8660
768/768 [==============================] - 0s 58us/step - loss: 6.7354 - mse: 6.7354
神经网络减少了近 30%的 MSE。
结论
在与许多专业人士讨论 9/10 次后,回归模型将优于任何其他机器学习或人工智能算法。为什么即使 ML 和 AI 算法的准确率更高,也会出现这种情况?大多数时候,你是在向客户交付一个模型,或者需要根据模型的输出采取行动,并且必须告诉为什么。解释一个线性模型、它的假设以及为什么输出是这个样子是相对容易的。试图用一个神经网络来做这件事不仅会让人精疲力尽,而且会让那些没有参与开发过程的人感到非常困惑。
仅使用 Python 和 Numpy 的线性回归
用 Numpy 和 Python 写一个机器学习模型
在这篇文章中,我们将看到如何在不使用任何机器学习库的情况下用 Python 实现线性回归。在的另一篇文章中,我们看到了线性回归算法在理论上是如何工作的。随着机器学习库的流行,任何人都可以通过一些 API 调用来实现 ML 算法。但只有少数人深入了解算法是如何工作的。我们将使用 Python 编写线性回归程序,并对其进行训练!
Python 代码中的线性回归
我们将对线性回归算法进行编码,并用 Python 语言对其进行训练。如果你已经有编程经验,但不熟悉 Python,这绝对是轻而易举的事。然而,如果你没有任何编程经验,我建议你浏览 Python 的文档。只是为了对编程和语言语法有一个基本的了解。此外,Python 非常直观,您可以很快上手并运行。谷歌的 Colab 是运行你的程序的好方法,因为它在安装库时没有麻烦。但是如果你已经有了 Python IDE,欢迎你跳过。那好吧。事不宜迟,让我们直接跳到代码。
导入 Python 库
**import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import time**
首先我们导入最需要的矩阵运算库 Numpy。然后,‘matplotlib’是用来画草图和图形的。这是为了可视化我们的模型的拟合和性能。pandas 有助于将数据集(csv、excel 文件)轻松加载到 Pandas 数据框中。我们将使用这些来加载数据集,初始化线性回归模型并对其进行训练。
**df = pd.read_csv(“https://raw.githubusercontent.com/Baakchsu/LinearRegression/master/weight-height.csv”)**
这一行从我的 Github repo 中提取“根据体重预测身高”数据集,并将其读入数据框。
接下来,我们将为线性回归模型创建一个类,就像 scikit 的模型一样。它的模型可以用“sklearn.linear_model”调用。线性回归”方法。但是,我们将把它作为仅仅线性回归。让我们看看它是如何出现的。
创建线性回归类
**class LinearRegression:
def fit(self,X,Y):
X=np.array(X).reshape(-1,1)
Y=np.array(Y).reshape(-1,1)
x_shape = X.shape
self.parameter_cache = []
num_var = x_shape[1] #the shape corresponds to number of input variable dimensions. There’s only one for this dataset i.e weight of person
self.weight_matrix = np.random.normal(-1,1,(num_var,1))
self.intercept = np.random.rand(1)
for i in range(50):
self.dcostdm = np.sum(np.multiply(((np.matmul(X,self.weight_matrix)+self.intercept)-Y),X))*2/x_shape[0] #w.r.t to the weight
self.dcostdc = np.sum(((np.matmul(X,self.weight_matrix)+self.intercept)-Y))*2/x_shape[0] #partial derivative of cost w.r.t the intercept
self.weight_matrix -= 0.1*self.dcostdm #updating the weights with the calculated gradients
self.intercept -= 0.1*self.dcostdc #updating the weights with the calculated gradients
self.parameter_cache.append(np.array((self.weight_matrix,self.intercept))) #the parameters are cached just to track the progress
return self.weight_matrix,self.intercept,self.parameter_cache
def predict(self,X):
product = np.matmul(np.array(X).reshape(-1,1),self.weight_matrix)+self.intercept
return product**
结果很简单,对吧?让我们通过代码来更详细地理解一下。这里,我们用两个方法“拟合”和“预测”定义了 LinearRegression 类。是的,他们顾名思义。拟合方法接受输入特征向量(人的体重)和输出变量(人的身高),并训练线性模型以获得完美拟合。
**X=np.array(X).reshape(-1,1)
Y=np.array(Y).reshape(-1,1)
x_shape = X.shape
num_var = x_shape[1]**
我们将参数 X 和 Y 转换为 numpy 数组,并将它们重新整形为形状(数据的数量,特征变量的数量)。因为我们只是用体重来预测身高,所以变量的数量只有一个(num_var)。我们对输出目标变量 y 做同样的事情。
使用 Numpy 进行参数初始化
**self.weight_matrix = np.random.normal(-1,1,(num_var,1))
self.intercept = np.random.rand(1)
self.parameter_cache = [ ]**
之后,我们初始化权重矩阵和截距变量。权重矩阵将有一个形状(num_var,要预测的输出变量的数量)。因此,对于我们的问题,结果是(1,1)。因为输入和输出变量的数量都是一个(体重和身高都是一个变量)。如果我们用输入的体重和性别来预测一个人的身高,我们将有两个输入变量和一个输出变量。因此,权重矩阵将具有形状(2,1)。
截距只是一个表示线性回归模型的 Y 截距的数字。如果你对什么是权重和截距感到困惑,查看一下详细解释的前一篇文章。我们在训练时使用 parameter_cache 来缓存模型参数。
训练线性回归模型
**for i in range(50):
self.dcostdm = np.sum(np.multiply(((np.matmul(X,self.weight_matrix)+self.intercept)-Y),X))*2/x_shape[0] #partial derivative of cost w.r.t the weights
self.dcostdc = np.sum(((np.matmul(X,self.weight_matrix)+self.intercept)-Y))*2/x_shape[0] #partial derivative of cost w.r.t the intercept
self.weight_matrix -= 0.1*self.dcostdm #updating the weights with the calculated gradients
self.intercept -= 0.1*self.dcostdc #updating the weights with the calculated gradients
self.parameter_cache.append(np.array((self.weight_matrix,self.intercept)))****return self.weight_matrix,self.intercept,self.parameter_cache**
最后,我们用反向传播训练我们的模型。这是成本相对于(w.r.t)上一篇文章中的模型参数的偏导数方程。
成本 w.r.t 'm ‘(权重矩阵)的偏导数和成本函数相对于’ C '的偏导数
我们在前两行(dcostdm 和 dcostdc)中实现上述等式。
接下来,我们使用上面的等式用计算出的梯度更新参数“权重矩阵”和“截距”。然后,我们将模型参数追加到缓存中。训练循环结束后,我们从 fit 函数返回参数和缓存。
该预测方法
**def predict(self,X):
product = np.matmul(np.array(X).reshape(-1,1),self.weight_matrix)+self.intercept
return product**
预测方法采用输入要素,并使用线性回归类的训练参数预测输出。“self.weight_matrix”和“self.intercept”表示我们在拟合方法中看到的模型参数。同样,我们返回预测值。
我们如何使用模型类?
**reg = LinearRegression()**
到目前为止,我们只是创建了模型类和训练代码。现在,我们将使用上面的代码行创建一个线性回归类的实例。
**x = (df[‘Weight’]-df[‘Weight’].mean())/df[‘Weight’].std() #standardization of the dataset
y = (df[“Height”]-df[‘Height’].mean())/df[“Height”].std() #standardization of the dataset**
这两行将使用数学公式 X-u/std 对数据集进行标准化。其中,X 是我们想要标准化的变量,“u”是该变量的平均值,“std”是标准偏差。这有助于模型更快地学习,因为所有变量都在(-1 到 1)的范围内。它将平均值居中到 0 和单位标准偏差(std=1)。
**params = reg.fit(x[:-180],y[:-180])**
通过调用类实例‘reg’的 fit 方法并传递 X 和 Y 值,我们开始训练。这里,我们传递数据集,留下最后 180 个数据点进行测试。
模型可视化
**pred = reg.predict(np.array(x[-180:]))****plt.scatter(x[-180:],y[-180:])****plt.plot(x[-180:],pred)**
一旦我们完成训练,我们就可以使用训练好的回归模型进行预测。我们使用“reg.predict”方法来完成这项工作,并传入测试数据(最后 180 个数据点)。现在,“pred”变量将具有测试数据的预测输出。为了直观地显示模型是如何拟合的,我们首先用测试数据点创建一个图。然后,我们用“plt.plot”函数绘制模型拟合线。
对于用 Numpy 从头开始构建的线性回归模型,这提供了足够好的拟合。值得注意的是,从图中,我们可以看到它在数据集上概括得很好。这只是一个线性模型。但是知道它的工作原理有助于更好地应用它。
**plt.figure(figsize=(19, 10))
plt.scatter(x[-180:],y[-180:])
for i in list(np.arange(0,50,5)):
value = params[2][i]
prediction = np.matmul(np.array(x[-180:]).reshape(-1,1),value[0])+value[1]
plt.plot(x[-180:],prediction)**
从“fit”方法返回的参数缓存中,我们在训练过程中绘制出模型的拟合度。顶部的蓝线是训练前随机参数的初始拟合。如您所见,该模型在训练过程中提高了其预测性能。您可以修改代码,改变初始化条件,看看模型拟合如何变化。为此,可以在 GitHub 库上找到代码
展示模型如何改进拟合的历史
消费者金融新调查的线性回归
如何处理 SCF 的多个数据集
致谢:迈克尔·朗米尔
上个月,美联储发布了 2019 年美国家庭财务状况三年一度的调查:消费者财务调查(SCF)。尽管他们对 2016 年以来发生的变化做了很好的总结,但现在每个人都在想新冠肺炎对经济的影响,而美联储的总结只是一个脚注。
尽管如此,SCF 可以为未来分析 COVID 对我们财务状况的影响提供一个良好的前期基线。为 2019 年 SCF 进行的调查中,超过 90%发生在今年 2 月之前。任何分析中唯一真正的难题是理解如何准确地分析 SCF 最独特的特性之一:它有五个完整的数据集可以用于分析。
SCF 中的插补
为什么 SCF 会提供五个数据集?这主要是因为当人们接受调查采访时,他们没有提供完整的答案。
为了处理这些缺失的值,SCF 不是简单地根据一个家庭对其他问题的回答来猜测值,而是对他们的答案进行五次猜测。通过这种方式,研究人员可以更好地了解可能答案的分布情况。
尽管这种解决方案有助于解决丢失值的问题,但在对数据进行统计测试时,它会引入一个难题。这就好比你的新宜家书桌少了一个零件,而不是收到一个替换零件,而是收到了五套相同的新书桌。你会如何处理所有这些大公司?
当您试图对这些数据进行回归时,也会出现同样的问题。你只是用一套,用所有的,把它们叠起来吗?即使是训练有素的研究人员在试图分析数据时也会遇到问题。对 SAS 和 Stata 之类的统计包进行一些更新后,事情变得更容易了,但是 Python 需要做一些工作。让我们快速看一下 SCF 显示了什么。
检查数据
在这一部分的底部,您可以看到我用来将 SCF 数据下载到 Pandas 数据框中的代码要点。为了举例,让我们看看一个家庭的一些收入数据和股票所有权的市场价值及其所有的影响。
下面是 gist 中定义的函数如何工作及其输出的一个例子。
import pandas as pd
import dataloading as dltargetdir = “data/extracted/”df = dl.SCF_load_data(targetdir,
year=2019,
series=[‘yy1’, ‘y1’, ‘x3915’, ‘x5729’, ‘x42001’]
)df.head()
输出
正如你所看到的,2019 年数据集的前五行是第一个家庭的五个含义。看来这个家庭肯定没有任何股票,其收入以五种不同的方式估算。
这里需要注意的另一件事是权重。对于每一个牵连因素,权重代表该家庭在总人口中所代表的家庭数量。所以,如果你把五个数据集中的一个的所有家庭的权重加起来,你会得到一个接近 1.286 亿的数字,这是美国家庭的大概数量。
做出推论
有了这些数据,仍然有可能做出推论,但是你可能不得不偏离传统的方法。SCF 密码本指出蒙塔尔托和宋 (1996)提供了一个用户友好的介绍,介绍了如何利用具有多重含义的数据集进行推理。
首先,在这种情况发生之前,需要进行一些运算,以便进行我们的重复插补推断(RII)。需要做的一件事是创建一个新列来标识每一行属于哪个数据集。值得庆幸的是,估算数据的 id 是从家庭 id 构建的,并且可以成为一个新的列。此外,权重需要除以 5,以说明我们在所有数据集上为美国人口创建推断的事实。
# Add Implicate Numberdf[‘implicate’] = [x — y*10 for x, y in zip(df[‘imputed_hh_id’], df[‘household_id’])]# weighting dividing by 5 since data implicates being combined for regressiondf[‘across_imp_weighting’] = [x/5 for x in df[‘weighting’]]
下面是基于蒙塔尔托和宋(2006)描述的方法实现的代码示例。本质上,它采用系数和方差-协方差矩阵对每个影响进行回归,并生成独立变量的 p 值。举例来说,一个基于家庭所有股票资产的市场价值预测家庭总收入的模型显示 p 值接近于零,这是可以预料的。另一方面,过大的具有统计显著性的截距需要进一步研究。
dl.RII(df,
Xseries=[‘stock_mkt_value’],
y=’total_income’)
输出
进一步阅读
这篇文章将帮助你对 SCF 数据进行回归,但是如果你想进行一些其他类型的计算,我建议你阅读一下那里的学术文献。蒙塔尔托和宋(2006)肯定会提供一个很好的基础,在此基础上你可以建立更多的统计工具,以你需要的方式分析 SCF。
Python 中的简单线性回归
scikit 入门-学习和 Python
本文应该足以涵盖如何在 Python 中运行构造一个简单的线性回归。它也将包含一些我面对的错误和如何克服它们!
在 Unsplash 上由zdenk macha ek拍摄的照片
这个概念
简单线性回归
简而言之,线性回归是关于通过一组数据点找到一条最佳拟合线性线(通常由 R 平方度量来判断)。对于给定的 X 数据点,通过最小化实际和预测的 Y 数据点之间的差异(残差),该线将实现更好的拟合。在下面的例子中,蓝色点代表实际的 Y 值,而红色线代表预测的 Y 值的向量。
令人兴奋的是,简单的线性回归是监督机器学习最简单的形式之一!
数据
首先,我将使用 iris 数据集,它是数据空间中覆盖面非常广的数据集,可以很容易地在网上找到。它包含 5 个属性下的一组 150 个记录— 花瓣长度、花瓣宽度、萼片长度、萼片宽度和类(种)。
这里有一个快速的 iris_df.head() :
快速浏览数据集
包裹
- sklearn 模块(train_test_split、LinearRegression、make_regression、load _ iris)——这些模块在加载 iris 数据集、准备数据和拟合模型时是必需的。
- matplotlib pyploy 模块—需要绘制结果。
- 熊猫和 numpy 包——需要操纵数据帧及其组成值
该过程
我们将尝试解决的问题陈述是:
萼片长度和萼片宽度之间有线性关系吗?
代码块 1
- 我们首先从开始设置萼片长度为 X_var ,萼片宽度为 Y_var。
- 此外,有必要使用的**。对两个变量整形(-1,1)** 方法;这将在后面的部分详细阐述。
- **设置一个 75/25 列车测试分割。监督机器学习的一个关键思想是能够在未接触的数据上测试你的模型的能力。训练-测试分割实际上使用 75%来生成最佳拟合线,并使用剩余的 25%来评估模型对新数据(假设这些数据来自与训练数据集相同的分布)的性能。75/25 是 scikit learn,使用的默认比例,必要时可以更改。
代码块 2
4.创建线性回归对象,并使其符合训练数据。 LinearRegression() 可以认为是建立一个不含参数的‘空白’线性回归模型。呼唤着*。线性回归对象上的 fit(x_train,y_train)* 方法使用训练数据集和标签来为对象生成参数。
5.**获取线性回归模型的参数。*这是通过调用方法完成的。coef_ 和。在拟合的模型对象上截取 _ 。*末尾的下划线表示由模型生成。
6.**评估模型在训练和测试数据集上的表现。**在这种情况下,模型在训练数据上输出 0.0030 的 R 平方,在测试数据集上输出 0.0265 的 R 平方。在这种情况下,得出弱到不存在线性相关性的结论是合理的。
测绘
我们可以使用来自 matplotlib 库的 pyplot 模块进一步可视化数据。对于给定的萼片长度,似乎最佳拟合线提供了对萼片宽度的非常不准确的预测。这与低 R 平方分数相一致。
因此,我们可以得出结论,在这些花的萼片宽度和萼片长度之间存在微弱或不存在的线性回归。
代码块 3
可能的问题
错误消息!
如上所述,我称之为*。在继续建模之前,对变量进行整形(-1,1)* 方法。下面不用重塑的方法来试试吧。线性回归模型抛出了一个令人生畏的错误,但是需要重点关注的是最后几行:
应为 2D 数组,却得到了 1D 数组,和要么使用 array . shape(-1,1)对数据进行整形(如果数据只有一个要素),要么使用 array . shape(1,-1)对数据进行整形(如果数据只有一个样本)。
基本上,。fit 方法期望 x 和 y 变量是二维数组,但它们最终是原始形式的一维数组。为了确认,我们可以打电话给*。shape* 方法,它们都将返回各自 numpy (150,)的形状。这可以解释为第一维度具有 150 个值,而第二维度包含 0,从而产生一维对象。进一步调用。ndim 方法对变量将返回维数,1。
**这个。 reshape(-1,1) 方法用于创建原始数组的一个实例,该实例添加了一个额外的 numpy 数组维度。**该方法的参数具有以下含义:
- -1:保持尺寸不变。
- 1:添加新尺寸。
这样一来,X_var 和 Y_var 现在就转化成了带的变量。2 的 ndim ,和。(150,1)的形状。**在此过程中,变量也从类型pandas . core . series . series变为类型 numpy.ndarray.
代码
请在这里找到我的 GitHub 上的代码:
GitHub 是超过 5000 万开发者的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/dehan97/fictional-fiesta/blob/master/scikit%20linear%20regs.ipynb)
我希望我能够以这样或那样的方式帮助您学习数据科学方法——如果有,请留下评论!
如果你有问题或者想讨论在后新冠肺炎时代应用数据科学技术的想法,请随时联系我。
这是另一篇数据科学文章!
了解岭回归模型背后的理论,如何通过 python 和 scikit-learn 对其进行编码和调优。
medium.com](https://medium.com/python-in-plain-english/ridge-regressions-on-easy-mode-9e7353a0e3f9)
基于霍夫变换的直线检测
一种在图像中寻找直线的算法
使用霍夫变换算法的直线检测
**注:**你可以在这里阅读这篇文章的中文版。
一.动机
最近,我发现自己不得不将文档扫描仪功能整合到一个应用程序中。在做了一些研究后,我看到了 Dropbox 机器学习团队成员熊英写的一篇文章。的文章解释了 Dropbox 的机器学习团队如何通过强调他们经历的步骤以及每个步骤中使用的算法来实现他们的文档扫描仪(熊,2016)。通过那篇文章,我了解了一种叫做霍夫变换的方法,以及如何用它来检测图像中的线条。因此,在本文中,我将解释霍夫变换算法,并提供该算法在 Python 中的“从头”实现。
二。霍夫变换
霍夫变换是一种由 Paul V. C. Hough 申请专利的算法,最初被发明用于识别照片中的复杂线条(Hough,1962)。自开始以来,该算法已经被修改和增强,以便能够识别其他形状,例如特定类型的圆形和四边形。为了理解 Hough 变换算法如何工作,理解四个概念是很重要的:边缘图像、Hough 空间、边缘点到 Hough 空间的映射、表示线的另一种方法以及如何检测线。
边缘图像
Canny 边缘检测算法。来源:艾窝棚
边缘图像是边缘检测算法的输出。边缘检测算法通过确定图像的亮度/强度发生剧烈变化的位置来检测图像中的边缘(“边缘检测-使用 Python 进行图像处理”,2020)。边缘检测算法的例子有: Canny 、 Sobel 、 Laplacian 等。边缘图像被二值化是很常见的,这意味着它的所有像素值不是 1 就是 0。根据您的情况,1 或 0 可以表示边缘像素。对于霍夫变换算法,首先执行边缘检测以产生边缘图像是至关重要的,该边缘图像随后将被用作算法的输入。
霍夫空间和边缘点到霍夫空间的映射
从边缘点到霍夫空间的映射。
霍夫空间是 2D 平面,其水平轴代表斜率,垂直轴代表边缘图像上的线的截距。边缘图像上的一条线用 y = ax + b 的形式表示(Hough,1962)。边缘图像上的一条线在霍夫空间上产生一个点,因为一条线由其斜率 a 和截距 b 来表征。另一方面,边缘图像上的边缘点( xᵢ 、 yᵢ )可以有无限多条线穿过。因此,一个边缘点在霍夫空间产生一条直线,其形式为b =axᵢ+yᵢ(leaves,1992)。在霍夫变换算法中,霍夫空间用于确定边缘图像中是否存在直线。
表示线条的另一种方式
计算直线斜率的方程式。
以y = ax+b**的形式表示线条以及带有斜率和截距的霍夫空间有一个缺陷。在这种形式下,该算法将无法检测垂直线,因为斜率 a 对于垂直线是未定义的/无穷大(Leavers,1992)。从程序上来说,这意味着计算机需要无限的内存来表示一个的所有可能值。为了避免这个问题,直线由一条称为法线的线来表示,该线穿过原点并垂直于该直线。法线的形式为ρ= x cos(θ)+y sin(θ)其中ρ 为法线的长度,θ为法线与 x 轴的夹角。
直线及其对应霍夫空间的替代表示。
使用这个,代替用斜率 a 和截距 b 表示霍夫空间,现在用ρ和θ表示霍夫空间,其中横轴表示θ值,纵轴表示ρ值。边缘点到霍夫空间的映射以类似的方式工作,除了边缘点( x ᵢ, y ᵢ)现在在霍夫空间中产生余弦曲线而不是直线(leavers,1992)。线的这种正常表示消除了处理垂直线时出现的 a 的无界值的问题。
线检测
检测图像中线的过程。霍夫空间中的黄点表示存在直线,由θ和ρ对表示。
如上所述,边缘点在霍夫空间中产生余弦曲线。由此,如果我们将边缘图像中的所有边缘点映射到霍夫空间,将会生成大量的余弦曲线。如果两个边缘点位于同一直线上,它们对应的余弦曲线将在特定的(ρ,θ)对上相交。因此,霍夫变换算法通过找到具有大于某个阈值的相交数的(ρ,θ)对来检测直线。值得注意的是,如果不进行一些预处理,如霍夫空间上的邻域抑制,以去除边缘图像中的相似线,这种阈值方法可能不总是产生最佳结果。
三。该算法
- 决定ρ和θ的范围。通常,θ的范围是[ 0,180 ]度, ρ 是[ - d , d ,其中 d 是边缘图像对角线的长度。量化ρ和θ的范围很重要,这意味着应该有有限数量的可能值。
- 创建一个名为累加器的 2D 数组,表示维数为( num_rhos , num_thetas )的霍夫空间,并将其所有值初始化为零。
- 对原始图像执行边缘检测。这可以用你选择的任何边缘检测算法来完成。
- 对于边缘图像上的每个像素,检查该像素是否是边缘像素。如果是边缘像素,则遍历θ的所有可能值,计算相应的ρ,在累加器中找到θ和ρ索引,并基于这些索引对递增累加器。
- 遍历累加器中的所有值。如果该值大于某个阈值,则获取ρ和θ指数,从指数对中获取ρ和θ的值,然后可以将其转换回形式 y = ax + b 。
四。代码
非矢量化解决方案
使用霍夫变换的直线检测(非矢量化)
矢量化解决方案
使用霍夫变换的直线检测(矢量化)
动词 (verb 的缩写)结论
总之,本文以最简单的形式展示了霍夫变换算法。如上所述,该算法可以扩展到检测直线之外。多年来,对该算法进行了许多改进,使其能够检测其他形状,如圆形、三角形,甚至特定形状的四边形。这导致了许多有用的现实世界应用,从文件扫描到自动驾驶汽车的车道检测。我相信,在可预见的未来,这种算法将推动更多令人惊叹的技术。
喜欢这篇文章并想表示支持?跟着我或者给我买咖啡
参考
边缘检测—使用 Python 进行图像处理。(2020 年 2 月 16 日)。检索自https://data uniform . org/image-processing/08-edge-detection/
霍夫公司(1962 年)。识别复杂图案的方法和手段(美国专利 3069654)。检索自https://patent images . storage . Google APIs . com/9f/9f/F3/87610 dec 32390/us 3069654 . pdf
离开者,V. F. (1992)。预处理,使用霍夫变换在计算机视觉中进行形状检测(第 39–64 页)。doi:10.1007/978–1–4471–1940–1
林,c .(2018 . 12 . 17)。教程:搭建车道检测器。走向数据科学。检索自https://towardsdatascience . com/tutorial-build-a-lane-detector-679 FD 8953132
Mukhopadhyay,p .和 Chaudhuria,B. B. (2015 年)。霍夫变换综述。模式识别。 48 (3),993–1010。从 https://doi.org/10.1016/j.patcog.2014.08.027取回
史密斯,B. (2018 年 9 月 21 日)。霍夫圆变换。ImageJ。从 https://imagej.net/Hough_Circle_Transform取回
索达,S. (2017 年)。索贝尔边缘检测的实现。projectrhea.org。检索自https://www . project Rhea . org/Rhea/index . PHP/An _ Implementation _ of _ Sobel _ Edge _ Detection
霍夫变换。(未注明)。从 https://aishack.in/tutorials/hough-transform-basics/取回
熊,于(2016)。快速准确的扫描文件检测。检索自https://Dropbox . tech/machine-learning/fast-and-accurate-document-detection-for-scanning
Twitter 上的链接分析
在混乱中寻找秩序
(来源:推特和 NodeXL。作者的合成图像)
如果你是一个经常使用 Twitter 的用户,你会习惯于政治咆哮、糟糕的笑话、动物视频和阴谋论的混乱混乱,这已经成为我们日常生活的一部分。
但是当你深入挖掘时,会发现一组结构良好的数据,可以挖掘出对塑造 Twitterverse 的关系的有意义的见解。据估计,每天有 5 亿条推文在 Twitter 上发送。这相当于每秒 5787 次。但是如果你把注意力集中在大量数据中有意义的子集上,你就能理解它。
在这篇文章中,我将介绍一些可用于获取、分析和可视化数据的工具和技术,以区分 Twitter 影响者和那些只是在空白空间大喊大叫的人。我还将介绍 NodeXL ,这是一个网络可视化工具,可以让您更轻松地分析数据。
我将使用图形数据库技术,它将您的数据构建为节点和节点间连接的网络,而不是传统的行和列。我在之前的两篇文章中写过关于图形数据库技术的使用:‘我如何学会不再担心并爱上图形数据库和’布加洛黑社会’。
获取数据
与脸书和其他社交媒体平台相比,Twitter 对开发者和数据分析师要友好得多。 Twitter API 为开发人员提供了进行我将要演示的网络图分析所需的所有数据。在大多数情况下,无论你使用的是 API 还是我下面概述的工具,Twitter 都会将你对历史数据的访问限制在不超过 7 天之前。
但是如果你想要比 Twitter API 更快更简单的东西,只需看看标签(即“Twitter 存档谷歌表”)。TAGS 是由 Martin Hawksey (@mhawksey)开发的一个“爱好”项目,是一个免费的谷歌表单模板,允许您通过用户名、标签和其他参数检索推文。
标签用户界面。(来源:TAGS)
如果您想要实时收集数据,您可以在 TAGS 中设置您的作业,并让它运行几天。您的数据将被存储在 Google sheet 中,并可以下载到. csv 或 Excel 文件中以供进一步分析。关于设置和使用标签的完整说明可在标签网站上找到。
另一个获取数据的简单方法是 Socialbearing.com 的,它允许你通过用户名、标签和其他参数进行搜索。结果在仪表板中返回(见下文)。您可以下载. csv 格式的底层数据进行分析。虽然从 Socialbearing 获得基本数据是免费的,但更专业的报告,如超过通常 7 天 Twitter 限制的报告,是可以付费的。
Socialbearing.com 仪表板。(来源:Socialbearing.com)
对于下面的分析,只关注转发是很重要的。这是因为大多数专家认为,某人被转发的频率是衡量他们影响力的最佳指标。底线是你可以整天发微博。但其他人的转发是衡量其他人是否真的在关注的最佳标准。
数据准备
无论您使用什么方法来检索数据,您都会惊讶于它的结构有多好。但是在准备分析之前还有一点工作要做。首先,您需要从推文文本中提取关于谁被转发的信息。转发的文本以“RT @ ”开头,后面是原始推文的文本。
如何提取将取决于您准备数据所使用的工具。在我的例子中,我首先将数据导入 Tableau,并使用下面的正则表达式从每条 tweet 的文本中提取转发信息:
LOWER(REGEXP_EXTRACT([text],’ \ @([a-zA-Z0–9 _]+)'))
如果您使用其他东西,正则表达式的逻辑如下:
它在名为“text”的列中搜索“@”符号,后跟任何大小写字母和数字以及“_”的字符串。“LOWER()”函数将提取的内容转换成小写,以避免相同的用户名根据大小写被计算两次。提取的任何内容都需要放入新的列中。
由于分析集中在转发上,您还需要一个显示推文类型的列。
如果你用 Socialbearing.com 下载你的数据,你会发现,对于每条推文,它已经有一个标签为“推文类型”的栏,你可以用它来过滤掉除了转发以外的任何内容。
如果你使用标签,你必须采取额外的步骤从推文文本中提取转发数据。使用 Tableau,我能够通过以下语句从 tweet 的文本中获得我需要的内容:
如果包含([Text]," RT @ “)那么” retweet"
ELSEIF 包含([Text]," @ “)那么” @ reference "
ELSE "原始推文"结束
这其中的逻辑很容易理解。如果这条推文的文本包含“RT @ ”,那它就是一条转发。如果它包含“@”而没有“RT”,则意味着提到了一个用户。这是另一个潜在的影响力衡量标准,但我不会在下面的分析中使用它。如果这两个条件都不适用,它就会被贴上“原创推特”的标签。
最后,您需要重组数据,以便在 NodeXL 这样的网络分析工具中使用。有两种主要的数据类型:
节点(node XL 中也称为“顶点”):网络中的数据点。例如,在下面的分析中,每个 Twitter 用户都是一个节点。
边:节点之间的关系。如果一个 Twitter 用户转发了另一个用户,那么图上他们之间的线就是一条边。
这里的一项分析研究了特朗普总统最有可能转发谁,下图显示了这种结构。它由一个“转发者”列和一个“发起者”列组成,前者针对发送转发的用户,后者针对推文的发起者。我还添加了一个“计数”列,显示每个发起人转发特朗普的次数。
在 NodeXL 中,每个 Twitter 用户或节点被称为“顶点”。而当与另一个用户配对在一起时,如下图所示,两者就成了一个“边”。包括计数是为了允许 NodeXL 在网络上运行一些基本的计算,并添加可视化增强。
为导入 NodeXL 而构造的数据。(来源:图片由作者提供)
介绍 NodeXL
NodeXL 是社交媒体研究基金会的一个项目。严格来说,它不是一个应用程序,而是一个下载并添加到 Microsoft Excel 中的模板。完成后,您就有了一套新的 Excel 工具来进行网络分析和可视化。
这是有代价的,尤其是对 Mac 用户和开源爱好者来说。NodeXL 只适用于 Microsoft Excel。而且还得有 Windows 版的 Excel。它不能在 Mac OS 版本上运行。
如果你不是 Windows 用户,NodeXL 建议运行基于云的 Windows 虚拟机,比如那些通过亚马逊弹性计算云提供的虚拟机。我在 Mac 上选择了本地 Windows 虚拟机,使用的是 Parallels 虚拟机。在我的测试中,NodeXL 在本地虚拟机上运行得很好,尽管有点慢。
NodeXL 可以处理的网络大小取决于系统 RAM。该产品的文档提供了以下估计:
- 4 GB 内存:只有不到几千条边的小型网络
- 8 GB 内存:小于 10–15 千条边的中型网络
- 16GB 内存:少于 8-10 万条边的大型网络
- 32 GB 内存:小于 20 万条边的超大型网络
下面两个例子中的一切都可以在 NodeXL 的基础版本上完成,这是免费的。高级功能,包括内容分析和高级网络度量,需要 NodeXL 的 Pro 版本,每年的费用从 39 美元到 799 美元不等,取决于你是学生,学术/非营利或商业用户。
要使用 NodeXL 的基础版本,你只需要在 SMRF 网站上注册,下载并安装它,就像任何其他 Windows 应用程序一样。它将在 Windows 开始菜单上显示为“NodeXL Excel 模板”。点击它,它将启动安装了 NodeXL 模板的 Excel。您将在 Excel 菜单功能区上看到一个“NodeXL Basic”项目,它展示了 NodeXL 的所有特性。
对 NodeXL 特性的全面解释超出了本文的范围。但是在 SMRF 网站上可以找到概述和文档。
川普转发宇宙
特朗普转发的 NodeXL 图。(来源:图片由作者提供)
上面的网络图是根据唐纳德·特朗普从 2020 年 1 月到 2020 年 4 月底的推文数据集创建的,共 3623 条推文,其中 1806 条是转发。
当放入网络分析所需的节点和边结构中时,总共有 497 条边,这显然是一个非常繁忙的图。一些过滤是适当的。我首先将数据限制在那些被特朗普转发五次或更多次的用户。然后,我删除了白宫工作人员和政治任命。最后,我删除了特朗普自己转发的那些内容,他已经这样做了 144 次。
我认为这给了我一个很好的画面,在他自己的小圈子之外,他倾向于发布得到特朗普认可的推文。
为了制作上图,我首先将节点和边数据导入 NodeXL 模板。下一步是为 NodeXL 图选择布局样式。我使用了 Fruchteman-Reingold 布局算法,这种算法可以避免边缘交叉带来的视觉混乱。Fruchteman-Reingold,加上特朗普与其他所有用户都有优势的数据集,产生了上面的圆形布局。
Fruchteman-Reingold 是一种被称为“力导向的算法我不会在这里深入讨论它(部分原因是我对它的理解相当初级),但是我发现在 NodeXL 中所有可用的算法中,它似乎最有可能产生一个整洁的、视觉上令人愉快的图形。
为了让图表更有趣,我使用 Twitter API 下载每个用户的个人资料图片,然后通过引用 NodeXL 模板中的文件名将图片放在图表上。我设置了每条边缘线的粗细,以对应每个用户发送的转发数量。
我根据用户类型设置了线条的颜色:红色代表共和党人,绿色代表媒体和名人,黑色代表其他人。这涉及到一些手工工作。对于特朗普的每一个转发收藏夹,我都检查了 Twitter 的个人资料,并在 NodeXL 模板中输入了适当的颜色。毫不奇怪,最有可能获得特朗普 8600 万粉丝转发的是众议院和参议院的共和党人。
NodeXL 用户界面。(来源:图片由作者提供)
#雅各布·布莱克
NodeXL #JacobBlake 转发图。(来源:图片由作者提供)
8 月 23 日下午,威斯康星州基诺沙市一名警察向 29 岁的黑人男子雅各布·布莱克(Jacob Blake)背部开了 7 枪。枪击事件如何发生的问题引发了两项调查:一项由地方、州和联邦当局进行;另一个在 Twitter 上,事情进展得更快。
上图显示了谁在 Twitter 上最成功地影响了公众对布莱克枪击案的看法。它基于枪击事件发生后三天内使用#JacobBlake 标签的转发,这一期间还包括一名亲警察抗议者用突击步枪杀害两名示威者。
这个图表有它的局限性。它只涵盖三天。特朗普图关注的是一个人和那些寻求他青睐的人,而像基诺沙这样的活动是动态的,不断有新用户加入,新标签不断出现。
该图的开发方式与 Trump graph 非常相似:将 Twitter 数据重组为一组节点和边,将其导入 NodeXL,并使用 Fruchteman-Reingold 算法绘制。但是这和有一个像 Trump 图这样的中心节点的区别是显而易见的。
有 1,156 名用户发送了#JacobBlake 推文,这些推文被转发。因此,再次需要一些过滤来创建一个可读的图表。在这种情况下,我使用 NodeXL 来计算一个称为“度中心性”的图度量,它基于到给定节点的连接数。我保留了图上的所有节点,但是只给那些中心度大于等于 100 的节点添加了标签和 tweet 内容。
NodeXL 的付费版本包括进行更复杂计算的能力,包括“特征向量中心性”,它根据节点与其他节点的连接程度来确定节点的得分。谷歌的“页面排名”算法,根据链接到一个给定网站的页面的良好连接程度对搜索结果进行排名,是同一想法的变体。
结论
总的来说,NodeXL 比我在以前的文章中提到的一些工具更容易使用,比如 Gephi 和 Neo4J 。NodeXL 没有那么强大,功能也不全。但是对于需要快速网络分析的有限数据集,我发现它是一个非常有用和通用的工具。它没有 Gephi 的怪癖,也不需要你像 NodeXL 一样建立一个成熟的图形数据库。如果你愿意走 Windows/Excel 路线,我强烈推荐。
最后,您可能会发现一些有用的资源:
如果你想深入了解 NodeXL,我找到的最佳资源是《T4》一书,“用 NodeXL 分析社交媒体网络”。Derek L. Hanson、Ben Shneiderman、Marc A. Smith 和 Itai Himelboim 撰写的《互联世界的洞见》。
关于分析社交网络的概述,你应该看看昆士兰(澳大利亚)科技大学提供的在线课程“社交媒体分析:使用数据理解公共对话”。
为了获得一些可以用 NodeXL 完成的工作的惊人例子,请看一下 NodeXL 图库。
对象-角色建模中的链接事实类型
对象-角色建模概念建模语言鲜为人知和理解的特性之一是链接事实类型。
为了理解链接事实类型,让我们看一个在哪里以及如何使用它们的例子。
想象一下下面的属性图模式,您正在为一个图数据库创建一个概念模型,该数据库存储库存软件解决方案的仓库中存储的零件信息:
库存图数据库的属性图模式
每个 StockedItem 代表一个零件,存放在仓库的一个箱中。注意被命名的边,代表,在中,在中。属性图模式的一个显著特征是命名边。因此,我们可以说“is for”边,StockedItem 和它表示为的部分之间的关系是 StockedItem 用于部分。
如果我们想象一个真实世界的场景,一个仓库保管员在仓库的箱子里拿一个零件,我们就会明白我们在说什么。
一名仓库保管员在仓库的箱子里寻找零件。图片经由Dreamstime.com授权给维克多·摩根特。ID 102810076 七十四张图片| Dreamstime.com
现在检查下面的对象-角色模型,它也代表仓库中箱柜中零件的概念模型:
对象-角色模型
请注意,从表面上看,每个 StockedItem 与事实类型读数没有关系,即, StockedItem 用于零件 , StockedItem 在仓位中,库存商品在仓库中。我们说,“从表面上看”,因为在 ORM 模型的这个视图中,我们没有显示每个对象化事实类型所隐含的链接事实类型,其中 StockedItem 是一个对象化事实类型。
Part is in Bin in Warehouse 是 ORM 中的一个事实类型,当被对象化时,我们可以把事实类型/关系看作是我们属性图模式中的一个表面节点。
现在让我们看看在我们的对象-角色模型中 StockedItem 的隐含链接事实类型。链接事实类型是带有虚线轮廓的事实类型:
具有链接事实类型的对象-角色模型
现在,我们有了事实类型读数,即,库存商品用于零件 , 库存商品在仓库中,库存商品在仓库中。
链接事实类型就是这么简单。对于每个对象化事实类型,都有一组隐含的事实类型,它们连接到在对象化事实类型中扮演角色的相应模型元素。
当然,对象-角色建模的美妙之处在于,一旦创建了 ORM 图,就可以将其转换为属性图模式或和实体关系图,如下所示:
实体关系图
请注意谓词部分“is for”、“is in”和“is in”,因为它们各自的关系也延续到我们的实体关系图中。
作为对象-角色建模的一个额外收获,您还可以捕获谓词“零件在仓库的箱子里”,进一步增加您正在创建的概念模型的语义。
感谢您的阅读。我希望这有助于理解链接事实类型以及它们在对象-角色建模中扮演的角色。
图片来源:ID 102810076 74 images | Dreamstime.com
=======================================
使用内核将您的虚拟环境链接到 Jupyter
立即开始原型制作。
简介:
当我第一次开始使用 Python 时,虚拟环境的概念对我来说非常难以理解。我经常花几个小时的时间来寻找和尝试创造一个,结果却比开始时更加困惑。
这篇文章旨在成为理解虚拟环境到底做什么,如何创建它们,以及将它们链接到你的 Jupyter 笔记本的一站式商店。
目录:
- 什么是虚拟环境?
- 使用 Anaconda 创建一个环境
- 将软件包安装到环境中
- 使用 Jupyter 中的虚拟环境作为内核
- 删除环境和内核
什么是虚拟环境?
我们先从鲍勃的故事说起。
Bob 在一家大型金融公司担任数据科学家。Bob 和他的团队都使用 Python,并定期在某些项目上相互协作。然而,由于这家金融公司规模很大,他们都有大量的个人项目。因此,需要一种通用的方法来将这些项目相互分离,以确保它们可以在任何安装了 Python 的计算机上运行。这就是虚拟环境发挥作用的地方。
你可以把一个虚拟环境想象成你电脑中 Python 的 特定副本,你可以指定自己。这个副本可以是安装了任何包的任何版本的 Python。使用虚拟环境可以确保项目之间存在一定的障碍。这些障碍确保任何人都可以运行您的 Python 版本,不管他们的计算机上有什么。**
使用 Anaconda 创建一个环境
我将在本教程中使用 Anaconda,因为它使得创建和维护虚拟环境变得极其容易。如果你没有下载,你可以在 Anaconda 的网站上设置个人版。完全下载可能需要一些时间。
如果您允许 Anaconda 设置一个路径变量,那么您可以在您的命令提示符下执行我的操作。如果没有,您仍然可以在下载文件附带的 Anaconda 提示符下遵循这些步骤。
让我们首先从创建一个新环境开始。我将把它命名为tutorial
,但是你可以随便叫它:
*$ conda create -n tutorial python=3.7*
注意事项:
-n
表示虚拟环境的名称python=3.7
是可选的,可以改成任何版本。我更喜欢在创建环境时设置一个特定的版本,因为它会给你一个“基本的”Python 环境。- 您将被要求继续安装一组软件包。键入
y
并按回车键。
作者图片
将软件包安装到环境中
现在我们的环境已经创建好了,Anaconda 给了我们一个提示。
*#
# To activate this environment, use
#
# $ conda activate tutorial
#
# To deactivate an active environment, use
#
# $ conda deactivate*
所以我们会这样做。激活我们的环境:
*$ conda activate tutorial*
这是我们应该期待看到的:
作者图片
请注意,当我们激活虚拟环境时,括号中的虚拟环境名称是如何出现的。这就是我们如何知道我们在环境中。
要安装软件包,我们可以像安装其他软件包一样使用pip
。由于本文的目的是让我们也能使用 Jupyter 中的虚拟环境,我们将安装ipykernel
来为我们完成这项工作。但是,您可以在这个阶段为您的项目安装任何需要的包。
*$ pip install ipykernel*
让提示符运行并安装ipykernel
。我们现在可以为 Jupyter 创建 Python 内核。
使用 Jupyter 中的虚拟环境作为内核
使用 Jupyter 笔记本时,您可以使用纯文本或代码。我们使用的代码块是内核。我们可以用ipykernel
创建新的内核。
当我们创建内核时,我们可以将它链接到我们的虚拟环境。当您正在创建一个新项目并且不确定您需要的必要包时,这将变得非常有用。无论您删除三分之二的已安装软件包还是再安装一个,内核将始终镜像我们创建的虚拟环境。
为此:
*$ python -m ipykernel install --user --name=tutorial*
作者图片
现在要验证内核是否在我们的 Jupyter 笔记本中:
作者图片
如你所见,tutorial
现在是我们的一个内核了。我们现在可以利用这种环境创建新的笔记本电脑,或者利用现有的采用这种新内核的笔记本电脑。
删除环境和内核
出于管理目的,我还将向您展示如何逆转我们在本文中已经完成的内容。首先,停用您的虚拟环境。
*$ conda deactivate*
你应该看到(tutorial)
走开。
移除内核:
首先,查看计算机上的内核列表。如果您在阅读本文之前从未这样做过,那么您应该会看到两个内核的列表:Python 3 和我们刚刚创建的内核。
*$ jupyter kernelspec list*
作者图片
现在我们知道我们有什么,我们知道要删除什么。要删除内核,请使用下面的命令。您将被要求再次与y
确认。
*$ jupyter kernelspec remove tutorial*
一旦完成,用jupyter kernelspec list
再次确认它已被移除。
作者图片
删除环境:
删除虚拟环境基本上遵循与删除内核相同的过程。首先,查看我们拥有的环境列表:
*$ conda env list*
作者图片
如果您的列表中没有blind-source-separation
,请不要担心。这是我亲自参与的项目之一。你应该期待看到base
和tutorial
。要移除tutorial
:
*$ conda env remove -n tutorial*
删除后,查看环境列表进行验证。
作者图片
结论:
我希望这篇教程能帮助你理解如何创建虚拟环境,并把它们链接到你的 Jupyter 笔记本上。请随意保存这篇文章,以节省您一次又一次搜索这些程序的时间。
感谢您的阅读。
Python 中的链表
Python 中的链表数据结构
数据结构提供了组织数据的方法,这样我们就可以有效地对数据进行操作。一个重要的数据结构是链表。链表是节点的线性集合,其中每个节点包含一个数据值和对列表中下一个节点的引用。在这篇文章中,我们将讨论如何在 python 中实现链表。
我们开始吧!
我们首先创建两个类,一个“Node”类和一个“LinkedList”类。对于节点类,我们有:
class Node:
def __init__(self, data):
self.data = data
self.next = None
这里我们分配数据值,并将下一个节点初始化为 null。对于“LinkedList”类,我们将头节点初始化为 null:
class LinkedList:
def __init__(self):
self.head = None
链表类将包含节点类类型的引用,用于初始化链表对象。我们现在可以编写一个链表的实例并打印结果:
if __name__=='__main__':
linkedlist = LinkedList()
print(linked list)
我们看到在指定的地址有一个链表对象。接下来我们可以定义几个节点。让我们来举一个现实生活中的例子。音乐播放器通常具有包含链接到上一首和下一首歌曲的歌曲的双向链表。为了简单起见,让我们考虑歌曲的单向链表,其中每首歌曲将只链接到下一首歌曲。
让我们创建一个由平克·弗洛伊德创作的专辑前半部分的歌曲的链接列表。首先,我们定义每个节点的值:
if __name__=='__main__':
linkedlist = LinkedList()
linkedlist.head = Node('Speak to Me')
second = Node('Breathe')
third = Node('On the Run')
fourth = Node('Time')
fifth = Node('The Great Gig in the Sky')
现在我们需要连接所有的节点。首先,我们定义头节点的“下一个”值:
linkedlist.head.next **=** second
然后是“第二个”节点的“下一个”值:
second.next **=** third
以此类推:
third.next **=** fourth
fourth.next **=** fifth
现在我们的链表已经定义好了,我们可以遍历链表了。让我们在“LinkedList”类中定义一个允许我们这样做的方法:
def printLinkedList(self):
value = self.head
while (value):
print(value.data)
value = value.next
我们现在可以遍历列表:
if __name__=='__main__':
#initialize linked list object
linkedlist = LinkedList()
print(linkedlist)
#assign values to nodes
linkedlist.head = Node('Speak to Me')
second = Node('Breathe')
third = Node('On the Run')
fourth = Node('Time')
fifth = Node('The Great Gig in the Sky')
#link nodes
linkedlist.head.next = second
second.next = third
third.next = fourth
fourth.next = fifth
linkedlist.printLinkedList()
总之,在这篇文章中,我们讨论了如何在 python 中实现一个单链表。我们为音乐播放器开发了一个单链表,其中每首歌曲都链接到列表中的下一首歌曲。实际上,音乐播放器中的歌曲链接到上一首和下一首歌曲(双向链表实现)。我鼓励你修改这篇文章中的代码,为我们使用的歌曲实现一个双向链表。这篇文章中的代码可以在 GitHub 上找到。感谢您的阅读!
LinkedIn API + Python =编程发布
如何通过 LinkedIn API 和 Python 发布帖子
费伦茨·霍瓦特在 Unsplash 上的照片
pointerpodcast . it 问题
我和我的另外两个朋友有一个播客,每次我们发布新的一集,我们都需要在社交网站上传播它(也就是垃圾邮件)。
在不同的社交网站上复制粘贴同一篇文章的重复动作让我们很烦恼。因此,我们决定开发我们的网络应用程序,让我们可以一次在多个平台上发布一篇帖子!
作者截图
我们成功整合了脸书、Instagram、Twitter 和我们的电报频道。
我们非常开心。
gif via GIPHY[https://media.giphy.com/media/wrzf9P70YWLJK/giphy.gif]
然后,LinkedIn 来了。
gif via GIPHY[https://media.giphy.com/media/2m0n9crL33MDLASKnj/giphy.gif]
任务
当您编程时,您希望以最快的方式开发您的应用程序。一旦成功了,你就可以开始修改代码了。
然而,这种匆忙必然导致文档中隐藏的一些重要细节的丢失。你猜怎么着?你的代码不会工作,你会发疯的。
几天后,你会发现它不起作用的“原因”。您的反应类型可以分为两类:
- 你觉得自己很蠢。“这很明显!我怎么会没注意到呢?”
- 你对 LinkedIn 很生气,因为不提供“现成的”文档是不允许的!
你属于哪一种?
gif via GIPHY[https://media.giphy.com/media/lI0Qg3f4o1IS4/giphy.gif]
因此,我的任务是提出一个超级实用的分步指南来通过 Python 与 LinkedIn API 交互。就是这样。
我在这里!—Gif via GIPHY[https://media.giphy.com/media/z0mMFvI7U27V6/giphy.gif]
掌握 LinkedIn API 的超级实用指南
- 在 LinkedIn 开发者平台上创建你的 LinkedIn 应用。
- 获取您需要整合到 Python 应用程序中的访问令牌。
- 开发剧本,让它发挥作用!
你准备好了吗?
gif via GIPHY[【https://media.giphy.com/media/CjmvTCZf2U3p09Cn0h/giphy.gif】T2]
1。创建你的 LinkedIn 应用程序
去 LinkedIn 开发者平台。
[## 开发者| Linkedin
编辑描述
www.linkedin.com](https://www.linkedin.com/developers/)
然后点击创建 app
作者截图
提供要求的数据
作者截图
点击“验证”来验证您的 LinkedIn 页面
作者截图
点击“生成 URL ”,按照 LinkedIn 要求的几个步骤进行操作
作者截图
完成后,如果一切正常,你会在你的应用主页上看到“已验证”
作者截图
转到“产品”并启用“LinkedIn 上的共享”和“营销开发人员平台”产品
- “LinkedIn 上的共享”授权您通过 LinkedIn API 管理您的个人资料(在我的情况下,即 Alessandro Berti 账户 )
- “营销开发者平台”授权您通过 LinkedIn API 管理您的页面(即,在我的情况下,PointerPodcast page)
作者截图
⚠️:点击“市场开发人员平台,您将在您的主邮箱中收到以下申请表。⚠️
作者截图
⚠️:你需要填写它,否则,LinkedIn 不会授权你管理你的页面!⚠️
现在,LinkedIn 将审核你的请求。
耐心点,等答案。LinkedIn 会通过邮件联系你。
我的请求已在 2 天内获得批准
gif via GIPHY[https://media.giphy.com/media/xA1PKCt00IDew/giphy.gif]
您已成功创建并验证了您的应用程序!
很简单,不是吗?
gif via GIPHY[http://gph.is/2giD4LN]
在我们等待回应之前,让我们继续做其他的事情吧!
2.获取访问令牌
现在点击“认证”。在这里你可以找到你的客户 ID 和客户密码。
目前,只要记住他们在哪里。
作者截图
设置您的“应用程序的授权重定向 URL”。
注意下面的语法!/auth/linkedin/callback
是强制的!
https://example.com**/auth/linkedin/callback**
作者截图
是时候用一些代码弄脏自己的手了!
gif via GIPHY[https://media.giphy.com/media/l2SqhXKKs7HJHFkDS/giphy.gif]
要获得您的 访问令牌 ,您需要两个 REST 调用:
- 一个 GET 会把你重定向到一个新的网址。从这个 URL,您需要推断参数
code
中的值。 - 一个帖子将返回您全新的访问令牌。
让我们一步一步来!
1.得到
看看下面的网址就知道了。等待复制&粘贴之前!
**https://www.linkedin.com/oauth/v2/authorization?**
**response_type**=code&
**client_id**=YOUR_CLIENT_ID&
**redirect_uri**=https://example.com/auth/linkedin/callback& **state**=RandomString&
**scope**=w_member_social,r_liteprofile
⚠️→我说“等等”!←⚠️gif via giphy[https://media.giphy.com/media/xT1XGOSpbtYvl9HlGE/giphy.gif]
参数
response_type=code
*。*已经好了,复制就好。
cliend_id=*YOUR_CLIENT_ID*
*。*插入您在 LinkedIn 应用程序的 Auth 部分指定的客户 ID。
*redirect_uri=https://example.com/auth/linkedin/callback*
T40。插入您在 LinkedIn 应用程序的授权部分指定的授权重定向 URL。
state=RandomString
*。*随机选择您偏好的“RandomString”(即 ILovePointerPodcast )。
scope=w_member_social,r_liteprofile
*。*范围很重要!它指定了您需要的权限。
让我们简单点:
如果你计划在“阅读模式”下只与你自己的个人资料互动,那么
r_liteprofile
权限就足够了。如果您计划利用 LinkedIn API 在您自己的个人资料中发布帖子,您需要“写权限”(即
w_member_social)
)。
不过你可以像例子中的scope=w_member_social,r_liteprofile
一样,合成权限*。*
如果你打算使用 LinkedIn API 与你的页面进行交互,请继续阅读,直到⚠️⚠️ 阿奇通 ⚠️⚠️段落。
权限会根据您的需要而变化。如果您想进一步调查:
权限是对访问 LinkedIn 资源的授权同意。LinkedIn 平台使用权限来保护…
docs.microsoft.com](https://docs.microsoft.com/en-us/linkedin/shared/authentication/permissions?context=linkedin/context)
现在,你可以复制&粘贴下面的 GET url。
谢谢你的耐心。
https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=https://example.com/auth/linkedin/callback&state=RandomString&scope=w_member_social,r_liteprofile
把上面的链接( )贴上你正确的数据 )在你的浏览器里就行了。
如果你在正确的道路上,你会被重定向到这里:
作者截图
一旦点击中的标志,您将再次被重定向到一个空页面*!*
⚠️ →现在,看看这个空页面的新网址!← ⚠️
将其复制到便笺中。是这样吗?
[https://example.com/auth/linkedin/callback?**code=YOUR_CODE**&state=RandomString](https://62.171.188.29/auth/linkedin/callback?code=AQSGDHgqjQzx1igbzzI1DozOQjG6ulM3ykDQpte7UjI1Wvco27eOiMlPnGmTuY9gl7ckj1CN7N_ezI4GsT92GQiLyz6aX_2vLyPkHeX_zCD26A6p7j7XIS_BYOBdvf65q3nSi68twNd3SKbWVZ3v3otmf3qeX3jIjbPK8UyD1cPnePQf42wPbU_Lusrnlg&state=Piper2342)
复制code
参数的值(即YOUR_CODE
);我们需要它来正确地调用 POST。
⚠️⚠️ACHTUNG⚠️⚠️
gif via GIPHY[https://media.giphy.com/media/WZj3l2HIRubde/giphy.gif]
之前描述的获取只允许你管理你自己的个人资料账户,不能管理你的页面。要管理您的页面,您需要:
- 等待 LinkedIn 关于“营销开发者平台”的批准。
- 包含在的
*scope*
中得到、w_organization_social
的许可!(如果你打算“读取”你的页面上的数据,还需要添加*r_organization_social*
权限)。
⚠️如果你试图用w_organization_social
权限调用下面的 GET,但是你还没有收到对市场开发者平台的批准,那么 GET 将会失败 !⚠️
https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=https://example.com/auth/linkedin/callback&state=RandomString&scope=w_member_social,r_liteprofile,**w_organization_social**
因此,你必须等待 LinkedIn 的批准。
2.邮政
现在,是后通话时间!我们通过 bash 来做吧!
curl -d "grant_type=authorization_code&**code=YOUR_CODE**&redirect_uri=https://example.com/auth/linkedin/callback&**client_id=YOUR_CLIENT_ID**&**client_secret=YOUR_SECRET_ID**" -H "application/x-www-form-urlencoded" -X POST "www.linkedin.com/oauth/v2/accessToken"
你已经知道该怎么做了。对吗?
插入从 GET 获得的 YOUR_CODE 作为code
参数的值。
另外,插入您的客户 ID 和您的客户秘密。只是重复一句:“你可以在你的领英 App 的“Auth”页面中找到它们……”
跟随 POST 响应以及 访问令牌 !
作者截图
如果您请求了访问令牌和
*w_organization_social*
权限,那么上面的响应还将包含一个*refresh_token*
字段。复制
access_token
字段(不要弄丢了!)
gif via GIPHY[https://media.giphy.com/media/ie8I61aEWnJCM/giphy.gif]
让我们检查一下你的全新代币!
从你的 LinkedIn 应用程序中,点击“ Auth ”,然后点击“ token inspector ”。
作者截图
在表格中复制您的访问令牌,然后点击检查。
作者截图
检查权限是否与您在 GET 调用中指定的权限相对应。
如果是那样,你就完了!
作者截图
3.代码时间
与您自己的个人资料互动
为了能够与您的个人资料进行交互,您需要:
- 访问令牌(谁能想到?)
- 您的个人资料 ID
如何获取我的个人资料 ID ?让我们狂欢吧!
curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" -X GET "https://api.linkedin.com/v2/me"
输出:
id
字段是… 猜猜是什么?您的个人资料 ID !在我的情况下是: idBfR6bf7d
由作者在您自己的个人资料/代码上发布
更多 API:
[## 个人资料 API — LinkedIn
请注意,该 API 的使用仅限于 LinkedIn 批准的开发人员,并受适用数据的限制…
docs.microsoft.com](https://docs.microsoft.com/en-us/linkedin/shared/integrations/people/profile-api) [## LinkedIn 上的共享— LinkedIn
LinkedIn 是一个与你的社交网络分享内容的强大平台。确保您的内容收到…
docs.microsoft.com](https://docs.microsoft.com/en-us/linkedin/consumer/integrations/self-serve/share-on-linkedin?context=linkedin/consumer/context#overview)
与您的页面互动(组织/公司)
为了能够与您的页面进行交互,您需要:
- 访问令牌(连同
w_organization_social
- 您的页面 ID
我怎样才能得到我的页面 ID ?在“管理员视图中进入您的页面即可
作者截图
在我的情况下是:42331509
在您的页面上发布(组织/公司)/作者代码
更多 API:
LinkedIn 提供了一个分享和社交流 API 平台,会员可以通过它与他们的…
docs.microsoft.com](https://docs.microsoft.com/en-us/linkedin/marketing/integrations/community-management/shares)
但是等等!
一旦 LinkedIn 和接受了对“营销开发人员平台的审查,并且您已经重新生成了一个具有
**w_organization_social**
权限的新访问令牌,这最后一个脚本将立即生效!
gif via GIPHY[https://media.giphy.com/media/PkoJsjUUCwQBpRHEo3/giphy.gif]
那都是乡亲们!
我已经展示了一个非常简单的案例,但是既然它有效,您可以开始破解它,并基于所提供的 python 代码尝试任何其他更具体的 LinkedIn API!
希望这个超级实用的分步指南有用!
任何建议都超级欢迎!😃
[## Alessandro Berti 播客-pointer 播客| LinkedIn
查看 Alessandro Berti 在全球最大的职业社区 LinkedIn 上的个人资料。Alessandro 列出了 4 项工作…
www.linkedin.com](https://www.linkedin.com/in/aleberti/)
再见!😃—Gif via GIPHY[https://media.giphy.com/media/SH4bekOUGi5CE/giphy.gif]