你也可以计算回归模型 ROC 曲线
他们可能告诉你 ROC 曲线下的面积不能计算连续的目标变量。他们错了。下面是如何用 Python 实现的。
[作者图]
你是一家拍卖公司的数据科学家,你的老板让你建立一个模型来预测在售物品的锤价(即最终售价)。这种模式有两个目的:
- 为每件商品设定一个有意义的开价;
- 在拍卖过程中每隔一段时间放置最贵的物品。这样,你就会保持住观众的注意力。
因为您想要预测一个点值(以美元为单位),所以您决定使用一个回归模型(例如,XGBRegressor()
)。现在,你如何评价你的模型的性能?
让我们看看 Scikit 的回归模型度量工具箱:
Scikit-learn 的回归度量[ 链接 ]。
所有这些指标都试图量化模型预测与实际值的差距。事实上,如果你看一看他们的公式,你总会发现这个量:
实际值和模型预测值之间的差异。[作者图]
换句话说,这些指标非常有助于评估接近真实价格(第一个目标)的能力。但是它们对评估第二个目标毫无用处,第二个目标是将物品从最贵到最便宜排序的能力。
想要个例子吗?假设您的模型的第一个版本提供了这些结果:
y_true = [1000.0, 2000.0, 3000.0, 4000.0, 5000.0]
y_pred = [1100.0, 1300.0, 4000.0, 4800.0, 5200.0]
从图形上看,
在回归问题中比较真实值和预测值。[作者图]
如果拿mean_absolute_error(y_true, y_pred)
的话,得到 560 美金,大概不太好。但是,排名很完美!这意味着该模型完全能够辨别哪些物品将以更高的价格拍卖。
这是关于我们模型的一个非常重要的信息,这是我们从其他回归指标中感受不到的。但是我们如何衡量回归模型的排序能力呢?
评估预测模型排序能力的最流行的指标是roc_auc_score
。所以,让我们试着用我们的数据来计算一下…
[作者图]
我们得到一个错误!
这是因为roc_auc_score
只适用于分类模型,要么是一个类对 rest(“ovr”),要么是一个对一个(“ovo”)。Scikit-learn 希望找到离散的类到y_true
和y_pred
,而我们传递连续的值。
为此,我们需要将 **roc_auc_score**
的概念扩展到回归问题。我们将这样的度量标准称为regression_roc_auc_score
。在下一段中,我们将了解如何计算它。
寻找“回归 _roc_auc_score”
直观上,regression_roc_auc_score
应当具有以下性质:
- 和
roc_auc_score
一模一样,应该是有界在 0(最差可能排名)和 1(最好可能排名)之间,0.5 表示随机排名。 - 当目标变量为二进制时,
regression_roc_auc_score
必须给出与roc_auc_score
相同的结果(这样,这个度量将是roc_auc_score
的推广)。
现在,如何获得我们正在寻找的度量?
roc_auc_score
定义为 ROC 曲线下的面积,ROC 曲线是在所有分类阈值下,x 轴为假阳性率,y 轴为真阳性率的曲线。但是不可能用回归方法计算 FPR 和 TPR,所以我们不能走这条路。
幸运的是,我们有另一个定义。事实上,根据维基百科,roc_auc_score
与“一个分类器将随机选择的正面实例排列得比随机选择的负面实例更高的概率”相一致。
换句话说,如果我们取任意两个观察值 a 和 b 使得 a > b ,那么 **roc_auc_score**
等于我们的模型实际上排名 a 高于 b 的概率。
这个定义对我们更有用,因为它对回归也有意义(事实上 a 和 b 可能不限于 0 或 1,它们可以假设任何连续值);
此外,现在计算roc_auc_score
要容易得多。事实上,它归结为考虑每一对可能的项目 a 和 b ,这样 a > b ,并计算我们的模型对 a 的预测值实际上比对 b 的预测值高多少倍(最终的平局将被计算一半)。那么,roc_auc_score
就是成功的次数除以配对总数。
在 Python 中,这将是:
naive_roc_auc_score 的 Python 代码。[作者代码]
为了确保维基百科提供的定义是可靠的,让我们将我们的函数naive_roc_auc_score
与 Scikit-learn 的结果进行比较。
[作者图]
太好了!
如上所述——与 Scikit-learn 的roc_auc_score
不同——这个版本也适用于连续的目标变量。让我们试一试:
[作者图]
产量正是我们所期望的。排名是完美的,因此roc_auc_score
等于 1。
从天真到自举
一切看起来都很棒,但上面的实现有点幼稚。事实上,naive_roc_auc_score
评估每一对可能的观察值。这样就需要 O( n )次迭代(其中 n 为样本数),一旦 n 变大一点就变得不可用。
然而,如果我们不需要“精确”的答案,我们可以通过自举获得一个很好的近似值。我们可以使用许多随机选择的对,而不是评估每一个可能的对(这意味着不少于 n *( n +1)/2 对)。
这将转化为以下 Python 代码:
回归 _roc_auc_score 的 Python 代码。[作者代码]
regression_roc_auc_score
有三个参数:y_true
、y_pred
和num_rounds
。如果num_rounds
是整数,则作为随机对的个数来考虑(近似解)。然而,您也可以通过将字符串"exact"
传递给num_rounds
来计算“精确的”分数(即所有可能的配对)。
给我看一些真实的数据!
你很想看看函数regression_roc_auc_score
在真实数据集上的结果吗?我也是,所以让我们在一个经典数据集上使用它来解决回归问题:来自 StatLib 的 California Housing(数据可以直接从 Scikit-learn 导入,这是 BSD 许可下的)。
目标变量是加州各区的房价中值。该数据集由 20,640 个样本和 8 个观察到的特征组成。
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_splitX, y = fetch_california_housing(return_X_y = True, as_frame = True)
y *= 100000X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.33, random_state = 4321)
现在,让我们在训练集上尝试许多不同的模型,然后在测试集上计算一些指标(包括前面段落中定义的regression_roc_auc_score
)。
from sklearn.dummy import DummyRegressor
from sklearn.neighbors import KNeighborsRegressor
from sklearn.linear_model import LinearRegression
from sklearn.svm import SVR
from sklearn.neural_network import MLPRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import GradientBoostingRegressor
from xgboost import XGBRegressor
from catboost import CatBoostRegressor
from sklearn.metrics import mean_absolute_error, median_absolute_error, roc_auc_score, r2_score, explained_variance_scoremodelnames = [
‘DummyRegressor()’,
‘KNeighborsRegressor()’,
‘LinearRegression()’,
‘SVR()’,
‘MLPRegressor(hidden_layer_sizes = (16, 16))’,
‘DecisionTreeRegressor()’,
‘GradientBoostingRegressor()’,
‘XGBRegressor()’,
‘CatBoostRegressor()’
]metricnames = [
‘mean_absolute_error’,
‘median_absolute_error’,
‘r2_score’,
‘explained_variance_score’,
‘regression_roc_auc_score’
]metrics = pd.DataFrame(index = modelnames, columns = metricnames)for modelname in modelnames:
model = eval(modelname)
pred_test = model.fit(X_train, y_train).predict(X_test)
for metricname in metricnames:
metrics.loc[modelname, metricname] = eval(f'{metricname}(y_test, pred_test)')
下面的图比较了所有训练模型的regression_roc_auc_score
和mean_absolute_error
:
比较不同模型的 regression_roc_auc_score 和 mean_absolute_error。[作者图]
正如我们所料,这两个指标是反向相关的。当然,较低的mean_absolute_error
往往与较高的regression_roc_auc_score
联系在一起。
后一个指标提供了关于模型性能的额外知识:在计算了regression_roc_auc_score
之后,我们可以说,在给定 a > b 的情况下,Catboost 估计 a 比 b 更高的值的概率接近 90%。
感谢您的阅读!我希望你喜欢这篇文章。
我感谢反馈和建设性的批评。如果你想谈论这篇文章或其他相关话题,你可以发短信给我我的 Linkedin 联系人。
如何计算平均值和标准差—在 Pytorch 中归一化数据集
如果输入数据是标准化的,神经网络收敛得更快。了解如何计算自己数据集的平均值和标准差。
露丝·齐默曼在 Unsplash 上拍摄的照片
为什么归一化允许更快的收敛
数据集的规范化通常被视为一项相当平凡的任务,尽管它会强烈影响神经网络的性能。对于非标准化数据,特征的数值范围可能变化很大。以一个机器学习应用程序为例,在该应用程序中,房价是根据几个输入(表面积、年龄等)来预测的。表面积通常在 100 到 500 米之间,而年龄更可能在 0 到 25 岁之间。如果将这些原始数据输入到我们的机器学习模型中,将会出现缓慢的收敛。
如左图所示,搜索最陡的梯度,这在某种程度上是正确的方向,但也拥有相当大的振荡部分。这可以通过对学习率的推理来解释。表面积特征需要相对较大的学习速率,因为其范围相当大。但是这个大的学习率对于年龄来说太大了。优化器每一步都会超调,这会导致振荡,从而导致收敛缓慢。
标准化数据允许更快的收敛
可以通过减去每个特征的平均值( )并除以标准差(σ)来对数据进行归一化。这样,每个特征的平均值为 0,标准差为 1。这导致更快的收敛。
在机器视觉中,每个图像通道都是这样标准化的。
计算数据集的平均值和标准差
首先,需要一些进口。
我将使用 CIFAR 数据集及其彩色图像作为例子。但是,同样的代码也适用于灰度图像的 MNIST 数据集。
训练示例被下载并转换为张量,之后加载器获取 64 个图像的批次。
必须对所有图像、图像的高度和宽度计算平均值,但不能对通道进行计算。在彩色图像的情况下,期望大小为 3 的输出张量。
标准偏差可通过以下公式计算:
E[X ]表示平方数据的平均值,而(E[X])表示数据平均值的平方。
最后,计算 CIFAR 数据集的平均值和标准偏差。
Mean: tensor([0.4914, 0.4822, 0.4465])
Standard deviation: tensor([0.2471, 0.2435, 0.2616])
将标准化集成到您的 Pytorch 管道中
数据加载器必须结合这些标准化值,以便在训练过程中使用它们。因此,除了 ToTensor() 变换之外,随后是利用获得的值的归一化。
请注意,由于网络是在归一化图像上训练的,因此每个图像(无论是验证还是推断)都必须用相同的获得值进行归一化。
来自 CIFAR 数据集的归一化图像示例
结论
数据规范化是神经网络训练过程中的一个重要步骤。通过将数据归一化为 0 的统一平均值和 1 的标准偏差,可以实现更快的收敛。
如果您有任何问题,请随时联系我!
如何使用人工智能大写单词
NLP 的 truecasing 教程,带实际操作代码。
你有没有面对过一个庞大的文本语料库缺少单词的大写?在发表这篇文章之前,你需要大写 1000 个单词。在这篇文章中,我演示了如何自动修复文档中的案例信息。
布雷特·乔丹在 Unsplash 上拍摄的照片
真实大小写是一个自然语言处理问题,在没有信息的文本中找到单词的正确大写。
使用案例包括来自各种音频源的抄本、自动语音识别、光学字符识别、医疗记录、在线消息和游戏。原始文本源通常是匆忙生成的,大多数单词都是小写的。
有几种解决真实大小写问题的实用方法:
- 句子分割:将输入的文本分割成句子,并将每个句子的第一个单词大写。
- 词性标注:查找句子中每个单词的定义和上下文,并使用特定的标签大写单词,例如名词。
- 名称-实体-识别(NER) :将句子中的单词分类成特定的类别,并决定大写字母,例如人名等。
- 统计建模:对通常以大写格式出现的单词和一组单词训练一个统计模型。
我提出了一个简单的实际操作的 truecaser,它结合了句子分割和词性技术,如下所示。
算法正确地将单词 stone 的第一个实例识别为人名,应该大写。
该方法在不区分大小写的大型文档集上表现如何?下面我使用众所周知的 Yelp 数据集中的评论对代码进行子弹测试。文本在被我的代码处理之前是小写的。使用 BLEU score 将生成的大写文本与原始版本进行比较。
通过比较预测大写和真实大写之间的 n-grams 的数量,我们获得 86.71%作为真实大写修复质量的度量。
在这篇文章中,我讨论了 truecaser,将大小写信息恢复为大小写错误或无大小写的文本的过程,并且我提出了一个 truecaser,它与专业撰写的商业评论有 86%的一致性。真实大小写有助于其他 NLP 任务,如自动内容提取和机器翻译,以提高准确性。
如何在 Arduino 中捕获传感器数据,并使用 PySerial 在 Python 中读取它
实践教程
从 Arduino Nano 33 BLE 中获取传感器数据
传感器感知。它们能看到、听到和闻到我们人类无法(或不应该)看到、听到或闻到的东西。传感器数字化。通过视觉、听觉和嗅觉,他们量化和数字化我们的周围环境——他们创造数据。配备传感器的 Arduino 就是这种设备的一个例子。这些设备“感知”它们的周围环境,并用数据解释它们。也许你想知道如何提取这些数据。
本文解释了如何从 Arduino 中捕获多个传感器数据,并使用 Python 和库 PySerial 读取这些数据。我将使用的 Arduino 是 NANO 33 BLE ,这是一款配备了超过 5 个传感器的微处理器,除了其他功能之外,还可以测量温度、环境压力和湿度。在文章的第一部分,我将描述如何编写一个 Arduino 程序,从它的传感器获取数据;在第二部分,我将描述如何编写 Python 脚本来读取 Arduino 的数据并将其写入 CSV 文件。
我的 Arduino
步骤 1 —编写 Arduino 草图以捕捉传感器数据
在这一节中,我们将编写 Arduino 的草图(Arduino 程序的正式术语)来捕获传感器数据。我们一起经历吧。
#include <Arduino_HTS221.h> // Temperature sensor
#include <Arduino_LPS22HB.h> // Air pressure sensor
#include <Arduino_APDS9960.h> // Color, light, and proximity sensor
#include <Arduino_LSM9DS1.h> // Accelerometervoid setup() {
Serial.begin(9600);
while (!Serial);if (!HTS.begin()){
Serial.println("Failed to start the HTS221 sensor.");
while(1);
}if (!BARO.begin()) {
Serial.println("Failed to start the LPS22HB sensor.");
while (1);
}if (!APDS.begin()) {
Serial.println("Failed to start the APDS9960 sensor.");
while (1);
}if (!IMU.begin()) {
Serial.println("Failed to start the LSM9DS sensor.");
while (1);
}}void loop() {
// Read the temperature and humidity values
float temp = HTS.readTemperature(); // In C
float humidity = HTS.readHumidity(); // In %
float pressure = BARO.readPressure(); // In kPaint r, g, b, a;
APDS.readColor(r, g, b, a);float x, y, z;
IMU.readAcceleration(x, y, z);while (!APDS.colorAvailable() || !APDS.proximityAvailable())
{
}Serial.print(temp);
Serial.print(',');
Serial.print(humidity);
Serial.print(',');
Serial.print(pressure);
Serial.print(',');
Serial.print(r);
Serial.print(',');
Serial.print(b);
Serial.print(',');
Serial.print(g);
Serial.print(',');
Serial.print(a);
Serial.print(',');
Serial.print(x);
Serial.print(',');
Serial.print(y);
Serial.print(',');
Serial.print(z);
// Use Serial.println(); to add a linebreak// 10 mins
delay(600000);
}
我们的(C++)代码从加载传感器库的 include 语句开始。这些是:
加载完库之后,我们有了setup
函数,这个函数在草图开始时只被调用一次。在这里,我们将定义串行端口,我们希望在这里写入输出并初始化四个传感器。while
语句用于无限迭代,直到串口和传感器可用。
下面的函数是loop
,草图是主要程序,我们将在这里捕获传感器数据——该函数将永远运行,除非您终止它或出现错误。在前三行中,我们读取温度、湿度和压力值,并将它们分配给三个变量。接下来,我们将读取 APDS 传感器颜色红色、蓝色、绿色和环境光强度。(我应该提到,红色、蓝色和绿色不是标准的 RGB 颜色元组,其值的范围是从 0 到 255。相反,它们的值类似于红色、蓝色和绿色的强度。).为了读取颜色数据(使用APDS.readColor()
),我们将发送前面的四个变量作为参数,将读取的值传递给它们。类似地,我们将使用与颜色相同的方法读取加速度计数据。有了这些,我们就有了数据。
函数的后半部分涉及将捕获的值写入串行端口,以便稍后从 Python 中读取它们。在IMU.readAcceleration
之后,while
语句等待,直到 APDS 传感器上有颜色或接近度可用。一旦其中一个可用,程序将退出循环,并以逗号分隔( CSV )行的形式打印这些值,例如,“1,2,3,4,5”最后,我们将添加一个delay()
函数来暂停程序一段时间(以毫秒为单位),这段时间在参数中指定(您可以根据需要随意更改)。
接下来,我们将使用 Arduino IDE 将草图上传到 Arduino 板上,你可以从https://www.arduino.cc/en/software获得。你可以在 https://www.arduino.cc/en/Guide找到安装指南。
一旦安装并打开,我们需要安装 Arduino 板和传感器库。要安装板库,进入工具->-板->-板管理器,搜索“纳米 BLE”要安装传感器库,进入工具->-管理-库和**-搜索“HTS221”、“LPS22HB”、“APDS9960”和“LSM9DS1”现在,请将 Arduino 连接到电脑。然后点击“箭头”按钮将草图上传到 Arduino。为了确保它正在运行,进入工具**->-串行-监视器查看它的输出(图 1)。你会注意到缺少换行符。那很好。一旦我们从 Python 中读取数据,我们就不需要它了,这将在下一步中完成。
图一。打印的数据。这里我们有两组传感器读数,中间没有换行。我们将在 Python 端处理这个问题。
步骤 2 —使用 PySerial 读取 Python 中 Arduino 的数据
在第一步中,我们编写了一个 Arduino 草图,它从多个来源捕获传感器数据,并将它们打印到一个串行端口。在步骤 2 中,我们将编写一个 Python 脚本,它使用库 PySerial 逐行读取所述数据,因为 Arduino 将它打印到串行端口;要安装 PySerial,从您的终端执行$ pip install pyserial
。在读取数据时,我们将把值转换成一个列表,并在把列表附加到一个 CSV 文件之前把当前的本地时间戳添加到列表中。下面是完整的脚本。
import csv
from time import timeimport serial# Your serial port might be different!
ser = serial.Serial('/dev/cu.usbmodem141301', timeout=1)f = open("df.csv", "a+")
writer = csv.writer(f, delimiter=',')while True:
s = ser.readline().decode()
if s != "":
rows = [float(x) for x in s.split(',')]
# Insert local time to list's first position
rows.insert(0, int(time()))
print(rows)
writer.writerow(rows)
f.flush()
我们将通过导入我们将使用的库来启动脚本。这些是:
csv
:将数据写入 CSV 文件。time
:获取当前当地时间。serial
(PySerial):读取 Arduino 的数据。
接下来,我们需要声明我们的Serial
对象,以便从参数中指定的端口读取数据。在本例中,我从端口/dev/cu.usbmodem141301
读取数据,但这可能会因您的设置而异。为了找到正确的端口,我喜欢使用 Arduino IDE 的“端口”视图,您可以从工具->-端口中访问该视图(图 2)。这里你会看到两个串行端口:一个蓝牙和一个物理端口。你想要非蓝牙端口。将它的路径写在串行对象的第一个参数中。第二个参数 timeout 控制函数等待的时间(以秒为单位),直到所请求的字节数到达(我们将在后面添加)。如果请求的字节数在超时前没有到达,函数"返回在此之前收到的所有字节(py Serial 的串行类文档)。
图二。您可以从“工具”菜单中找到主板的串行端口。
因为我们的脚本将 Arduino 的数据写入一个 CSV 文件,所以我们需要一个csv.writer
对象将数据追加到文件中。编写器有两个参数,f
,目标文件和delimiter
" ,
"来指定哪个字符分隔字段。
现在我们写数据。为了无限期地运行我们的脚本,我们将使用一个while True
循环来读取发送到串行端口的最新行——注意,我们必须解码数据,因为它是以字节形式出现的。(说到字节,readline()
有一个参数 size s
用来指定函数最多会读取多少字节;我们将使用参数的默认值-1
来读取所有内容)。每当我们读一行,我们将检查它是否是空的。如果是,我们再次迭代。但是如果不是——这是令人兴奋的部分——我们将在将数据添加到文件之前对其进行预处理。
我们不会写入数据,因为它来自串行端口。相反,我们将对其进行预处理,并用本地时间对其进行扩展,以获得更丰富的数据集。在if
语句中,我们将使用 list comprehension 来创建一个新的列表,方法是分割字符串,使用字符",
"作为分隔符(因为这是我们在 Arduino 上打印数据的方式),并将值从字符串转换为浮点数。对于这个列表,我们将在它的第一个位置插入当前本地时间戳(以秒为单位)。然后,我们将打印它,将其写入 CSV,并在之后刷新该文件。就这样,我们结束了!
要运行脚本,请执行命令$ python main.py
。如果您得到一个类似这样的错误,
FileNotFoundError: [Errno 2] No such file or directory: '/dev/cu.usbmodem141301'
这意味着定义的串口是错误的或不可用的。我再次建议使用 Arduino IDE 来找到正确的端口。另一种方法是列出端口,如以下网址所述:https://www . mathworks . com/help/support pkg/arduinoio/ug/find-arduino-port-on-windows-MAC-and-Linux . html。运行脚本几分钟后,返回 CSV 文件查找数据。下面的图 3 显示了我的一个例子。
图 3。我的 CSV 文件样本。缺少列名;我没有从脚本中添加它们,以防你使用我以外的数据。
总结和结论
我们人类正以稳定的节奏赋予科技感知的能力。会达到类似人类的水平吗?我不知道。但是根据基于感知的人工智能(正如李博士在他的书人工智能超能力中所讨论的)的准确性和用例来判断,例如物体探测器,我们可以肯定地说,它会让我们怀疑我们人类在某些任务中是否优越。
在本文中,我们没有构建这样的人工智能。相反,我们收集了我们需要的数据,以防我们想要建立一个。为了收集数据,我们在 NANO 33 BLE 设备中编写并部署了一个 Arduino 草图,该设备配备了可以捕捉温度、压力、湿度、亮度和加速度数据的传感器。为了导出数据,我们编写了一个 Python 脚本,从 Arduino 中读取数据,并将其写入一个 CSV 文件。
你会用它来建造什么?您将如何使用这个新数据集?由于这个 Arduino 支持用于微控制器的 TensorFlow Lite】,这是一个用于在微控制器上执行 TensorFlow 模型的 TensorFlow C++库,我计划用数据构建一个模型,并将其部署在设备上。模型会做什么?目前为止还没想。但不管是什么任务,我肯定它会比我做得更好。
你可以在https://github . com/juandes/arduino-content/blob/main/sketches/get _ sensor _ data/sketch/sketch . ino找到草图代码,在https://github . com/juandes/arduino-content/blob/main/Python/py serial/main . py找到 Python 脚本。
如何捕获 Power BI 生成的 SQL 查询
面带微笑,向您的 DBA 提供关于 Power BI 生成的 SQL 查询的所有必要信息
https://www . pexels . com/photo/cute-dog-in-bright-shirt-on-light-background-5733428/
从前,你那吓人的老 DBA 红着脸走进你的办公室,愤怒地问你:“你到底对你的 Power BI 报告做了什么?!它扼杀了我们所有的工作负载!!!"
你知道他为什么生气,甚至在他对你大喊大叫之前。这是因为使用 DirectQuery 的“那个”报告,因为您的用户想要“接近实时”的数据…
我已经写了为什么你应该重新考虑使用 DirectQuery ,以及在什么情况下(可能)走这条路是有意义的。
然而,看起来您的 DBA 并没有您想象的那么“糟糕”。他提出帮助您优化最详尽的 SQL 查询,他只是希望您将这些查询发送给他…
哦,等等,当我在 Power BI 中“看不到”SQL 查询时,我如何向他发送这些查询呢?!别担心,有多种方法可以捕获 Power BI 引擎生成的 SQL 查询。
SQL Server 事件探查器—面向传统人士!
https://www . pexels . com/photo/vintage-car-on-parking-in-mountains-5480749/
在我向您展示如何使用优秀的 SQL Server Management Studio (SSMS)及其内置功能 SQL Server Profiler 之前,让我简单解释一下后台发生的事情:Power BI Desktop 启动了分析服务表格式的本地实例。因此,您可以使用 SQL Server 事件探查器像跟踪任何其他事件一样跟踪此实例。
像往常一样,我将在所有示例中使用示例 Contoso 数据库。
您要做的第一件事是打开 SSMS 工具栏下的 SQL Server Profiler:
作者图片
我的 Power BI 报告相当简单,它只包含三种视觉效果:
作者图片
关于 DirectQuery,要记住的最重要的事情是——每当您与报表进行交互时,每个视觉对象都将向数据源发出查询,即使您没有与特定的视觉对象进行交互!在我的示例中,每当我对报表进行操作时,就会有两个单独的查询被发送到底层的 Contoso SQL 数据库。
让我们打开 SQL Server Profiler,检查一下发生了什么:
作者图片
在这里,您可以看到,当我更改我的日期切片器的值时,Power BI 触发了两个单独的查询(针对我们的每个视觉效果)!您可以在 SQL: BatchCompleted 事件类下看到关于每个查询的更多细节:执行用了多长时间,进行了多少次读取,等等。
但是,最重要的是,您可以捕获 Power BI 生成的 SQL:
作者图片
现在,您可以复制这个查询并发送给您的 DBA,这样他就可以决定是否有性能改进的空间(可能是添加索引或者其他什么)。
无论如何,您现在已经准备好帮助查找影响常规工作负载的 SQL 查询了。
DAX Studio —简单而优雅的解决方案!
https://www . pexels . com/photo/cute-dog-in-bright-shirt-on-light-background-5733428/
如果您不熟悉 SQL Server Profiler 和其他“传统”工具(当我说传统时,我指的是您的 DBA 喜欢的工具:)),您可以利用 Power BI Desktop 本身的性能分析器特性,与 DAX Studio 协同工作,以达到相同的效果!
作者图片
只需刷新视觉效果,您应该能够在报告画布上看到每个视觉效果的总时间:
作者图片
选择复制查询选项,然后直接进入 DAX Studio。将复制的查询粘贴到主窗口后,向下滚动,您将看到 SQL 查询!多酷啊!
作者图片
我有一个额外的建议给你!如果您有多个查询(例如我们的例子中有两个,但有时可能会有 10 个以上),那么来回移动、一个接一个地复制和粘贴查询会非常麻烦。
您应该在 DAX Studio 中启用“所有查询”按钮,并等待几分钟,直到查询跟踪开始:
作者图片
现在,回到 Power BI Desktop 并刷新视觉效果。完成后,再次打开 DAX Studio 并转到所有查询选项卡:
作者图片
瞧——我所有的查询现在都被一次捕获了!而且,一旦我关闭“所有查询”选项卡并打开“服务器计时”选项卡,我就可以单击一个特定的查询:
作者图片
双击选定的查询后,DAX 代码将出现在主窗口中,因此我可以单击 Run,并转到底部的 Server Timings 选项卡:
作者图片
在那里,您不仅可以找到 Power BI 生成的 SQL 查询,还可以找到与服务器性能相关的不同指标,比如 CPU 时间。您还可以检查公式引擎(FE)和存储引擎(SE)满足请求所需的时间。
作者图片
结论
如您所见,有不同的方法来捕获 Power BI 生成的 SQL 查询。
您再也不需要担心了——下次您的 DBA 来到您的办公桌前时,请面带微笑,因为您现在可以为她/他提供在源(SQL 数据库)端微调 SQL 查询所需的所有信息了!
感谢阅读!
成为会员,阅读 Medium 上的每一个故事!
如何用 R 捕捉亵渎
忘了肥皂吧,我们会用数据科学的力量给他们洗洗嘴
泰勒·尼克斯在 Unsplash 上的照片
人们说脏话。如果你或你的公司碰巧有任何类型的用户生成内容,这些人会在你的网站、社交媒体、评论、评论等上说脏话。他们会匿名坐在他们的小屏幕后面,像海军陆战队队员一样在你的网站上骂人!
幸运的是,我曾经是一名海军陆战队员,所以我认为自己是骂人的专家。我将教你如何用几行 r 来捕捉亵渎。
问题比你想象的要大
在深入研究代码之前,让我们先思考一下这个问题是如何难以解决的。无论我们认为自己有多聪明,都比不上那些找到新方法骂人的人。仅 f-bomb 就有数千种变体,每天都有新的变体被创造出来(我在写这篇文章的时候就创造了几个新的!).
以下是你所面临的一些例子:
- 符号替换:cat = c@t
- 语音替换:duck = duc
- 大写替换:狗=干旱
- 字母分隔:goose = g o o s e
- 字符重复:mouse = moooouuuusssse
- 内心世界掩蔽:马=海马
- 语言替换:bird = pajaro
- 字母反转:rat = tar
- 还有很多很多其他人…
这排除了每个人的个人喜好,昨天还是良性的单词和短语今天可能突然变得具有攻击性。加分的是,这个词在世俗和非世俗的语境中都可以恰当地使用。
那么我们有机会吗?嗯,算是吧。
我们当然可以用黑名单和模式匹配来解决这个问题。)、机器学习和事后措施(例如暂停或禁止有毒用户)。但是没有什么能真正打败人类的节制。
语言变化的速度比我们的算法还快,我们的 ML 模型将永远与最后一个例子(一个好词一夜之间变坏)作斗争。
最好的方法通常是上述所有措施的结合。你想要黑名单(由人类版主每天添加新词),模式匹配来捕捉给定词的所有排列,ML 模型标记潜在的不良内容,以及足够严格的暂停/禁止措施来劝阻用户越过这条线。将所有这些与通过身份验证消除匿名结合起来,你可能就有机会了。
今天,我们将只关注第一项,通过黑名单捕捉亵渎。
不良
为了让你免于阅读一堆淘气的单词,我们要做一个小小的思维实验。就在今天,让我们假设“培根”、“莴苣”和“番茄”是英语中最卑鄙、最可怕、最亵渎的词汇。
如果你用脚趾踢床脚,你可能会说‘培根!!!'。如果你在祖母家说“番茄”,她可能会和你断绝关系,并把你从遗嘱中删除。如果你说“莴苣”这个词……你就明白了。
现在不要担心你不会学习如何真正抓住亵渎。我们将建立我们自己的不良词汇(又名黑名单),但你将能够使用我的代码通过交换一个变量来捕捉实际的亵渎。
漂亮的西红柿很酷,对吧?!
获取数据
现在我们已经确定 BLT 是不好的,我们需要找到一些 BLT。我们在哪里可以找到这些原料?在美食菜谱上怎么样!Kaggle 有一个免费的食物食谱数据集(Shuyang Li,“Food.com 食谱和互动。”卡格尔,2019,doi:10.34740/卡格尔/DSV/783630。)你可以从他们的网站上下载。该数据集被许可用于商业用途(CC BY 4.0)。
编写代码
首先打开 RStudio 并创建一个名为“ProfanityFinder”的新 R 项目。将 RAW_recipes.csv 放到项目的文件夹中。同时在这个项目中创建一个新的 R 脚本,名为“BadWords”。r ’
用你的话说。脚本,安装这些软件包你你还没有他们。Tidyverse 允许我们使用一些漂亮的管道语法来操作数据,sentimentr 有一些很棒的 NLP & profanity 函数。
接下来,我们将配方数据导入 tibble (Tidyverses 版本的 R 数据帧)。
现在我们的数据已经导入,让我们稍微清理一下。首先,我们只需要 name 和 ingredients 列,所以让我们选择它。
接下来,我们通过删除标点来清理成分栏。这个专栏有一些特殊的字符,比如方括号,它们会对我们的亵渎函数造成很大的破坏。我们将使用一行简单的代码来删除所有这些。
最后,食谱数据超过 230,000 行!虽然我们可以耐心地处理所有数据,但最好将其限制在 100 行以内。事实证明,如果不碰到一些熏肉、生菜和西红柿,你就无法深入了解食谱数据(请原谅我的法语!).
现在我们到了最精彩的部分。我们需要一个我们关心的不良词汇的列表。公司将这些列表称为黑名单或阻止列表。在 NLP 领域,我们通常将单词列表称为“词典”。不管你喜欢什么术语,让我们现在就建立它。
我们的词典是一个由三个顽皮单词组成的字符向量,它们被分配给一个名为 customCussWords 的变量。
注意了!这是魔法酱被搅拌的地方。我们的词典可能是一个简单的 3 个单词的列表,但是 sentimentr 包碰巧有相当多的实际不良单词的词典。想亲眼看看吗?在 RStudio 中,只需在控制台中键入我们的变量来读取其内容。
customCussWords
图片作者。
这里有一个警告,下面的命令会在你的控制台上显示一些非常可怕的单词。是时候开始锻炼你的铁胃了,因为事实证明你停止亵渎的方法就是用亵渎!
在运行 import(sentimentr)命令后,在控制台中键入以下命令,将会显示字符向量的内容,就像我们的“customCussWords”变量一样。
lexicon::profanity_alvarez
lexicon::profanity_banned
lexicon::profanity_arr_bad
这些只是一些不好的词汇。还有很多很多可以使用。为了更好的效果,为什么不把它们都结合起来。更好的是,定义你自己的!
那么所有这些意味着什么,我提到的神奇调味汁到底是什么?简单。无论你在哪里看到我们的 BLT 词典“自定义脏话”,你都可以用上面的脏话词典替换掉,现在你的代码会神奇地捕捉到脏话!
例如:
do_stuff(customCussWords)
可以变成:
do_stuff(lexicon::profanity_alvarez)
那么,我们实际上如何捕捉亵渎?sentimentr 包有一个方便的功能叫‘亵渎’!这个方便的函数有两个输入。第一个输入是文本,第二个输入是要与文本进行比较的单词词典!
让我们给亵渎函数一个旋转。首先,我们将使用一个不包含脏话的短语。
图片作者。
profanity 函数返回一个包含几个有趣列的表。它有元素和句子的 id、单词计数、亵渎计数,最后还有提供的文本中包含亵渎的单词的百分比。让我们在函数中加入一些诅咒,让它变得更有趣!
图片作者。
结果意味着我们有一个包含 3 个单词的句子,其中一个在我们的词典中找到。因为 1/3 的文章都是脏话,所以我们的脏话比例是 33%。
对于给定的文本,profanity 函数不仅返回 1 行。它实际上通过一个叫做“句子边界消歧”的过程将单词分解成句子。这是一种奇特的 NLP 语言,用于在我们的语言中寻找可能代表句子开始和结束的东西。
如果你还记得的话,我们之前已经删除了文本中所有的标点符号。句号是决定句子结束位置的众多方法之一。以下代码将从亵渎函数返回多行结果:
图片作者。
理解所有这些很重要,但是对于我们的简单练习,我们将只查看 profanity_count 列。我们可以 sum()这个列,以确保我们捕获了所有出现的句子!
使用 base R 语法,我们可以像这样访问特定的列:
图片作者。
万一有多个句子,我们可以这样总结:
图片作者。
现在我们知道了做这件事需要知道的一切!让我们获取配方数据,并使用 Tidyverse 添加一个带有 mutate()的列。
这是在做什么?
- 称我们的食谱为数据框架
- 行方式——对于每一行数据,执行以下操作
- mutate——添加一个新列,使用我们的 customCussWords 词典将配料列传递到 sentimentr 的亵渎函数中
- 过滤器-只显示有亵渎的记录
图片作者。
我们做到了!我们新的“亵渎计数”专栏正在查找并计算单词 bacon、莴苣和番茄的所有出现次数!
知道我们的文本中哪里存在亵渎是很好的,但是我们可以更进一步。让我们添加一列,返回我们的程序发现的实际亵渎。Sentimentr 确实有一个应该做这件事的函数(extract_profanity_terms),但至少在我拥有的 R 的构建上,这个函数似乎坏了。别担心,我们会写我们自己的函数!
我们的目标是将文本和词典传递给一个函数,并让它返回它能找到的所有熏肉、生菜和西红柿。再说一次,如果你需要找到真正的脏话,只需传递上面提到的一个词汇就可以了!
我们的函数在做什么?
- 我们定义了一个名为 returnText 的空字符
- 我们循环使用词典中的单词(培根、生菜、西红柿),看看这个单词是否在文本中。如果找到这个单词,Grepl 将返回 true 或 false。
- 如果找到这个单词,我们用粘贴函数把它附加到 returnText 变量中
- 我们退回所有找到的脏话。
最后,我们可以在代码中添加一个新的 mutate,将 recipe 传递给这个函数,它将像这样返回脏话:
图片作者。
就是这样!我们已经编写了在文本中发现亵渎的代码!
关于效率的一个注记
我们在这里写的代码在大多数小数据集上都能很好地工作,但是在一些场景中这是行不通的。
首先,句子边界消歧是一个代价很高的计算。如果您有一个较大的数据集,您会希望将所有文本预处理成句子。Sentimentr 有一个名为 get_sentences 的函数可以做到这一点。此外,从我们的数据中删除所有标点符号可能不是最明智的做法。您可能希望保留句点和感叹号,以帮助您的代码找出句子的开始和结束位置。
第二,我们编写的返回文本中的脏话的小循环并不是最有效的方法。你可以通过不同的方法获得更好的性能,比如 lapply,sapply 等。
最后,如果您试图标记实时数据或仔细阅读数十亿条记录,R 真的不适合这种语言。r 不完全是最快的编程语言,它的并行处理能力徘徊在“有限的和“不存在的”之间。如果您的用例涉及大量或实时数据,您会希望选择一种更接近机器的语言。
那是一个(BLT)包装!
现在你知道怎么抓坏人了吧!你可以从我的 GitHub 下载所有的代码!。
你知道你可以在一篇文章上点击鼓掌按钮多达 50 次吗?如果你觉得这篇文章内容丰富,那就把生菜从那玩意儿里砸出来!
如何更改 Pandas 数据框架中的列类型
探索在 pandas 中改变列的数据类型的 3 种不同选择
介绍
在处理熊猫数据帧时,最常见的操作之一是数据 类型(或 **dtype**
)转换。在今天的文章中,我们将探索 3 种不同的方法来改变熊猫的栏目类型。这些方法是
astype()
to_numeric()
convert_dtypes()
在开始讨论可以用来更改某些列的类型的各种选项之前,让我们首先创建一个伪数据帧,我们将在整篇文章中使用它作为示例。
import pandas as pddf = pd.DataFrame(
[
('1', 1, 'hi'),
('2', 2, 'bye'),
('3', 3, 'hello'),
('4', 4, 'goodbye'),
],
columns=list('ABC')
)print(df)# A B C
# 0 1 1 hi
# 1 2 2 bye
# 2 3 3 hello
# 3 4 4 goodbyeprint(df.dtypes)# A object
# B int64
# C object
# dtype: object
使用 astype()
[DataFrame.astype()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.astype.html)
方法用于将熊猫列转换为指定的数据类型。指定的 dtype 可以是内置 Python、numpy
或pandas
dtype。
假设我们想要将列A
(目前是一个类型为object
的字符串)转换成一个保存整数的列。为此,我们只需在 pandas DataFrame 对象上调用astype
,并显式定义我们希望转换列的 dtype。
**df['A'] = df['A'].astype(int)**print(df)# A B C
# 0 1 1 hi
# 1 2 2 bye
# 2 3 3 hello
# 3 4 4 goodbyeprint(df.dtypes)# A int64
# B int64
# C object
# dtype: object
您甚至可以一次转换多个列。举个例子,
**df = df.astype({"A": int, "B": str})**print(df)# A B C
# 0 1 1 hi
# 1 2 2 bye
# 2 3 3 hello
# 3 4 4 goodbyeprint(df.dtypes)# A int64
# B object
# C object
# dtype: object
此外,您甚至可以指示astype()
在观察到所提供的 dtype 的无效数据时如何行动。这可以通过传递相应的errors
参数来实现。您可以选择'raise’
无效数据异常或'ignore’
抑制异常。
例如,假设我们有一个混合了dtypes
和Series
的列,如下所示:
s = pd.Series(['1', '2', 'hello'])print(s)
# 0 1
# 1 2
# 2 hello
# dtype: object
现在,如果我们试图将该列转换为int
,将会引发一个ValueError
:
s = s.astype(int)
ValueError: invalid literal for int() with base 10: 'hello'
我们可以通过传递errors='ignore'
来抑制ValueError
。在这种情况下,原始对象将被返回
s = s.astype(int, errors='ignore')
print(s)# 0 1
# 1 2
# 2 hello
# dtype: object
从 1.3.0 版本开始,用于将时区简单类型转换为时区感知类型的 *astype*
已被弃用。你现在应该用 [*Series.dt.tz_localize()*](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.dt.tz_localize.html#pandas.Series.dt.tz_localize)
代替*。*
使用 to_numeric()
[pandas.to_numeric](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.to_numeric.html)
用于将非数字dtypes
列转换为最合适的数字时间。例如,为了将列A
转换为int
,您需要运行的全部内容是
**df['A'] = pd.to_numeric(df['A'])**print(df)
# A B C
# 0 1 1 hi
# 1 2 2 bye
# 2 3 3 hello
# 3 4 4 goodbyeprint(df.dtypes)
# A int64
# B int64
# C object
# dtype: object
现在,如果您想将多个列转换成数字,那么您必须使用如下所示的apply()
方法:
**df[["A", "B"]] = df[["A", "B"]].apply(pd.to_numeric)**print(df.dtypes)
# A int64
# B int64
# C object
# dtype: object
to_numeric()
也接受errors
参数(像astype()
一样),但是它有一个额外的选项,即*'*coerce*'*
将所有不能使用指定的dtype
解析的值设置为NaN
。要了解更多细节,请务必查看官方文档。
你可能还想看看 *to_datetime()*
和 *to_timedelta()*
方法,如果你想把一列分别投射到 *datetime*
或 *timedelta*
的话。
使用convert_dtypes()
[convert_dtypes()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.convert_dtypes.html#pandas.DataFrame.convert_dtypes)
方法包含在 pandas 版本1.0.0
中,用于使用支持pd.NA
(缺失值)的dtypes
将列转换为最佳的dtypes
。这意味着dtype
将在运行时根据指定列中包含的值来确定。
**df = df.convert_dtypes()**print(df.dtypes)# A string
# B Int64
# C string
# dtype: object
注意列 A 和 C 是如何被转换成string
类型的(最初它们是object
类型)。尽管这对于列C
来说相当准确,但理想情况下,我们希望将列A
转换为 int 列。如果你想让这个方法算出应该用什么dtypes
,这基本上是你必须付出的代价。如果这不是您所期待的,您仍然可以使用本文前面提到的任何方法来显式指定目标dtypes
。
最后的想法
在今天的文章中,我们探讨了 pandas 中的许多选项,可以用来转换数据帧中特定列的数据类型。我们讨论了如何使用astype()
来显式指定列的dtypes
。此外,我们还探索了如何使用to_numeric()
方法将列转换成数字类型。最后,我们展示了如何使用convert_dtypes()
方法,根据每个列中包含的值计算出最合适的dtypes
列。
如何更改 PySpark 数据帧的列名
讨论 PySpark 数据框架中改变列名的 5 种方法
照片由 Linus Nylund 在 Unsplash 上拍摄
介绍
在今天的简短指南中,我们将讨论在 Spark 数据帧中更改列名的 4 种方法。具体来说,我们将使用以下工具来探索如何做到这一点:
selectExpr()
方法withColumnRenamed()
方法toDF()
法- 别名
- Spark 会话和 Spark SQL
并一次重命名一列或多列。
首先,让我们创建一个示例 PySpark 数据帧,我们将在本指南中引用它来演示一些概念。
>>> from pyspark.sql import SparkSession# Create an instance of spark session
>>> spark_session = SparkSession.builder \
.master('local[1]') \
.appName('Example') \
.getOrCreate()>>> df = spark_session.createDataFrame(
[
(1, 'a', True, 1.0),
(2, 'b', False, 2.0),
(3, 'c', False, 3.0),
(4, 'd', True, 4.0),
],
['colA', 'colB', 'colC', 'colD']
)>>> df.show()
*+----+----+-----+----+
|colA|colB| colC|colD|
+----+----+-----+----+
| 1| a| true| 1.0|
| 2| b|false| 2.0|
| 3| c|false| 3.0|
| 4| d| true| 4.0|
+----+----+-----+----+*>>> df.printSchema()
*root
|-- colA: long (nullable = true)
|-- colB: string (nullable = true)
|-- colC: boolean (nullable = true)
|-- colD: double (nullable = true)*
使用 selectExpr()
第一个选项是[pyspark.sql.DataFrame.selectExpr()](https://spark.apache.org/docs/3.1.1/api/python/reference/api/pyspark.sql.DataFrame.selectExpr.html)
方法,它是接受 SQL 表达式的[select()](https://spark.apache.org/docs/3.1.1/api/python/reference/api/pyspark.sql.DataFrame.select.html#pyspark.sql.DataFrame.select)
方法的变体。
**>>> df = df.selectExpr(
'colA AS A',
'colB AS B',
'colC AS C',
'colD AS D',
)**>>> df.show()
*+---+---+-----+---+
| A| B| C| D|
+---+---+-----+---+
| 1| a| true|1.0|
| 2| b|false|2.0|
| 3| c|false|3.0|
| 4| d| true|4.0|
+---+---+-----+---+*
但是请注意,当您需要重命名大多数列,并且还必须处理相对较少的列时,这种方法最适合。
此时,您可能还想回忆一下 Spark 中select()
和selectExpr()
的区别:
使用 withColumnRenamed()
重命名 PySpark 数据帧列的第二个选项是[pyspark.sql.DataFrame.withColumnRenamed()](https://spark.apache.org/docs/latest/api/python/reference/api/pyspark.sql.DataFrame.withColumnRenamed.html)
。此方法通过重命名现有列来返回新的 DataFrame。
**>>> df = df.withColumnRenamed('colA', 'A')**>>> df.show()
*+---+----+-----+----+
| A|colB| colC|colD|
+---+----+-----+----+
| 1| a| true| 1.0|
| 2| b|false| 2.0|
| 3| c|false| 3.0|
| 4| d| true| 4.0|
+---+----+-----+----+*
当您需要一次重命名一列时,这种方法最合适。如果您需要一次性重命名多个列,那么本文中讨论的其他方法会更有帮助。
使用 toDF()方法
方法使用新的指定列名返回一个新的 DataFrame。
**>>> df = df.toDF('A', 'colB', 'C', 'colD')**>>> df.show()
*+---+----+-----+----+
| A|colB| C|colD|
+---+----+-----+----+
| 1| a| true| 1.0|
| 2| b|false| 2.0|
| 3| c|false| 3.0|
| 4| d| true| 4.0|
+---+----+-----+----+*
当您需要同时重命名多个列时,这种方法很有用。
请注意,如果您有一个包含新列名的列表,那么下面的代码也应该可以完成这个任务:
>>> new_col_names = ['A', 'colB', 'C', 'colD']
>>> **df = df.toDF(*new_col_names)**
使用别名
我们的另一个选择是使用[alias](https://spark.apache.org/docs/latest/api/python/reference/api/pyspark.sql.DataFrame.alias.html)
方法,返回一个带有别名集的新数据帧。
>>> from pyspark.sql.functions import col**>>> df = df.select(
** **col('colA').alias('A'),
col('colB'),
col('colC').alias('C'),
col('colD')** **)**>>> df.show()
*+---+----+-----+----+
| A|colB| C|colD|
+---+----+-----+----+
| 1| a| true| 1.0|
| 2| b|false| 2.0|
| 3| c|false| 3.0|
| 4| d| true| 4.0|
+---+----+-----+----+*
同样,当需要重命名多个列并且不需要处理大量列时,应该使用这种方法,否则这会变得非常冗长。
使用 Spark SQL
最后,您可以使用 Spark SQL 对存储为表的数据帧使用传统的 SQL 语法来重命名列。举个例子,
>>> df.createOrReplaceTempView('test_table')
>>> df = spark_session.sql(
'SELECT colA AS A, colB, colC AS C, colD FROM test_table'
)>>> df.show()
*+---+----+-----+----+
| A|colB| C|colD|
+---+----+-----+----+
| 1| a| true| 1.0|
| 2| b|false| 2.0|
| 3| c|false| 3.0|
| 4| d| true| 4.0|
+---+----+-----+----+*
最后的想法
在今天的简短指南中,我们讨论了如何以多种不同的方式重命名 PySpark 数据帧的列。根据您是否需要重命名一个或多个列,您必须选择最适合您的特定用例的方法。
成为会员 阅读媒介上的每一个故事。你的会员费直接支持我和你看的其他作家。
你可能也喜欢
如何改变熊猫数据框架中列的顺序
在 pandas 数据框架中更改列顺序并将列移到前面
介绍
对 pandas 数据帧中的列重新排序是我们想要执行的最常见的操作之一。当涉及到向其他人展示结果时,这通常是有用的,因为我们需要以某种逻辑顺序对(至少几个)列进行排序。
在今天的文章中,我们将讨论如何使用
- 原始帧的切片——当您需要重新排序大多数列时最相关
insert()
方法——如果你想将一个单独的列插入到指定的索引中set_index()
—如果需要将一列移动到数据框的前面- 和,
reindex()
方法——主要与您可以按照您希望的顺序指定列索引的情况相关(例如,按照字母顺序)
首先,让我们创建一个我们将在本指南中引用的示例数据帧。
import pandas as pddf = pd.DataFrame({
'colA':[1, 2, 3],
'colB': ['a', 'b', 'c'],
'colC': [True, False, False],
'colD': [10, 20, 30],
})print(df)
# colA colB colC colD
# 0 1 a True 10
# 1 2 b False 20
# 2 3 c False 30
使用切片
最简单的方法是使用一个列表分割原始数据帧,该列表包含您希望它们遵循的新顺序的列名:
**df = df[['colD', 'colB', 'colC', 'colA']]**print(df)
# colD colB colC colA
# 0 10 a True 1
# 1 20 b False 2
# 2 30 c False 3
如果您想对大多数列的名称进行重新排序,这种方法可能已经足够好了(而且您的数据框架可能有太多的列)。
使用 insert()方法
如果您需要将列插入数据帧的指定位置,那么[pandas.DataFrame.insert()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.insert.html)
应该可以做到。但是,您应该确保首先将该列从原始数据帧中取出,否则将出现一个带有以下消息的ValueError
:
ValueError: cannot insert column_name, already exists
因此,在调用insert()
之前,我们首先需要对数据帧执行[pop()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.pop.html)
操作,以便从原始数据帧中删除该列并保留其信息。例如,如果我们想将colD
作为框架的第一列,我们首先需要pop()
该列,然后将其插回,这次是插入到所需的索引。
**col = df.pop("colD")
df.insert(0, col.name, col)** print(df)
# colD colA colB colC
# 0 10 1 a True
# 1 20 2 b False
# 2 30 3 c False
使用 set_index()方法
如果你想把一列移到熊猫数据框的前面,那么[set_index()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.set_index.html)
就是你的朋友。
首先,您指定我们希望移到前面的列作为数据帧的索引,然后重置索引,以便旧的索引作为一列添加,并使用新的顺序索引。同样,请注意我们如何pop()
在将列添加为索引之前删除它。这是必需的,否则当试图使旧索引成为数据帧的第一列时会发生名称冲突。
**df.set_index(df.pop('colD'), inplace=True)**# colA colB colC
# colD
# 10 1 a True
# 20 2 b False
# 30 3 c False**df.reset_index(inplace=True)**# colD colA colB colC
# 0 10 1 a True
# 1 20 2 b False
# 2 30 3 c False
使用 reindex()方法
最后,如果您想要按照您希望的顺序指定列索引(例如按字母顺序),您可以使用[reindex()](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.reindex.html)
方法使数据帧符合新的索引。
例如,假设我们需要按字母降序排列列名
**df = df.reindex(columns=sorted(df.columns, reverse=True))**# colD colC colB colA
# 0 10 True a 1
# 1 20 False b 2
# 2 30 False c 3
请注意,上述内容相当于
df.reindex(sorted(df.columns, reverse=True), axis='columns')
最后的想法
在今天的简短指南中,我们讨论了如何以多种不同的方式改变熊猫数据帧中的列顺序。确保根据您的具体要求选择正确的方法。
你可能也会喜欢
如何用数据科学改变世界
利用数据科学的力量应对全球挑战
朱莉安娜·科佐斯基在 Unsplash 上的照片
只有当我们收集的数据能够通知和激励那些有能力做出改变的人时,事情才能完成
如今,全球有近百万人在数据科学相关领域工作。
该行业经历了巨大的增长,全球大部分数据都是在过去两年中生成的。数据驱动的行业在过去几年里经历了巨大的增长。
数据科学的应用让生活变得更加轻松。从寻找最好的电影到选择最好的餐馆就餐,数据为我们提供了比我们可能需要的更多的便利。
当今世界,几乎所有数据科学的应用都致力于让已经舒适的生活变得更加舒适。
然而,我们可以利用现有的数据做更多的事情。用于促进销售的相同算法可以被编写为相反促进社会影响。
如何利用数据科学造福社会?
利用数据科学造福社会的一些例子包括:
- 创建机器学习算法来预测家庭的贫困状况。
- 识别网络欺凌和自杀之间的趋势。
- 检查不同街道特征对行人死亡的影响。
- 确定社交媒体使用的个性化算法是否会强化负面的身体形象。
现在是创造数据驱动的解决方案来解决社会问题的最佳时机。收集与上述所有主题相关的大量数据是可能的。
非营利组织可以利用这些数据更好地理解社会问题。如果他们所做的工作是由数据驱动的,他们将能够在实现社会问题的解决方案方面迈出更大的步伐。
例如,可以实现机器学习模型来识别需要立即关注的社区,并对它们进行优先排序。
然而,为了社会利益,在数据科学领域取得进展是很困难的。虽然大型科技公司有能力聘请数据科学家并开发大型数据生态系统,但非营利组织负担不起。
这意味着,尽管非政府组织拥有丰富的数据,但他们无法利用这些数据,因为他们缺乏技术技能。
幸运的是,有一些组织帮助非政府组织获得技术人才。
这些组织将数据科学家/分析师与世界各地的非政府组织配对。
事实上,如果你是一名有抱负的数据科学家,你可以在其中一个组织中做志愿者。您将能够与其他行业专业人士合作,分析社会数据并回答紧迫的问题。
你如何参与其中
在 Unsplash 上由 Etty Fidele 拍摄的照片
“使用数据不仅可以决定我们想看什么样的电影,还可以决定我们想看什么样的世界”——data kind
DataKind 是一个连接数据科学家和非政府组织的组织。他们甚至为想要涉足社会科学的数据科学家提供指导。
他们的座右铭是 “利用数据科学的力量为人类服务。”
如果你是一名想要回馈社会的数据科学家,你可以加入 DataKind 成为一名志愿者。如果你作为志愿者加入,他们会将你分配到一个现有的项目中,你将与一群志同道合的人一起回答一个社会数据科学问题。
截至目前,他们正在进行的最受欢迎的项目之一叫做零视力。这个项目旨在将与交通相关的伤亡降至零。
他们的大多数活动都是在晚上或周末组织的,所以全职工作的人也可以积极参与。你可以在这里了解更多关于 DataKind 做的工作。
华威大学也有一个 DSSG(社会公益数据科学)暑期奖学金,做的工作和 DataKind 类似。他们教导学生与非政府组织合作,为社会公益开发数据科学产品。你可以在这里看一看他们做的一些工作。
社会数据科学有更多的奖学金和志愿者机会,所以如果你对此感兴趣,你应该做一些研究。
您可以参与的项目
如果你想在社会数据科学领域做一些研究,这里有一些项目想法给你:
分析 BLM 运动
照片由 Gabe Pierce 在 Unsplash 上拍摄
作为对系统性种族主义的回应,一场名为“黑人的命也是命”的民众运动应运而生。这场运动抗议警察暴行和黑人在日常生活中面临的其他形式的暴力。
然而,BLM 运动受到了其他社区的强烈反对。很多人不愿意相信系统性种族主义的存在。他们说像 BLM 这样的运动是不必要的。
像“所有生命都重要”这样的运动是对 BLM 运动的回应,他们坚持认为美国是一个后种族社会,种族主义在这个国家已经不存在了。
数据可以用来证明黑人社区是否处于劣势。纽约警察局每天都会发布交通堵塞数据。
每个交通站的细节都被记录下来,这些数据可以用来寻找系统性种族主义的证据。它可以用来回答像这样的问题,“少数民族是否更经常被警察拦下,却没有更多犯罪证据?”
如果这是你感兴趣的分析,你应该看看斯坦福开放警务项目。
贫困预测
为了消除极端贫困,定期对其进行衡量非常重要。非政府组织只有不时地对其减贫战略进行评估,才能了解其是否有效。
如果我们要确定贫困,我们首先需要收集家庭消费数据。然后,我们可以在带标签的贫困数据集上训练机器学习模型,并对未来数据进行预测。
有了好的算法,我们可以快速识别低收入家庭。这些预测可以帮助社会组织优先考虑低收入家庭,并制定减贫战略。
如果这是一个你感兴趣的项目,你应该看看 Kaggle 的贫困预测数据集。
结论
大多数现有的数据驱动解决方案都专注于提高人们日常生活的舒适度。虽然这是产生最多收入的数据科学应用,但它肯定不是最有意义的应用。
数据有可能为人们创造更好的生活,并可用于解决贫困、药物滥用和种族主义等问题。
应用数据科学来解决社会问题被称为社会数据科学,可以产生改变世界的影响。
如何使用 scikit-learn 检查分类模型是否过度拟合
数据分析
Python 中的现成教程,有助于识别和减少过度拟合
在处理机器学习算法时,最困难的问题之一是评估经过训练的模型在未知样本下是否表现良好。例如,可能会发生这样的情况:模型在给定的数据集下表现很好,但在部署时却无法预测正确的值。训练数据和测试数据之间的这种不一致可能是由不同的问题造成的。最常见的问题之一是过度拟合。
一个模型很好地适应了训练集,但测试集很差,这种模型被称为对训练集过度适应,而一个模型对两个集都不太适应,这种模型被称为欠适应。摘自这篇非常有趣的文章作者 Joe Kadi。
换句话说,过度拟合意味着机器学习模型能够对训练集进行太好的建模。
在本教程中,我利用 Python scikit-learn
库来检查分类模型是否过度拟合。同样的程序也可以用于其他模型,如回归。提议的战略包括以下步骤:
- 将数据集分成训练集和测试集
- 用训练集训练模型
- 在训练集和测试集上测试模型
- 计算训练集和测试集的平均绝对误差(MAE)
- 绘制和解释结果
必须对不同的训练集和测试集执行前面的步骤。
作为示例数据集,我使用心脏病发作数据集,可在 Kaggle 存储库中获得。所有代码都可以从我的 Github 库下载。
加载数据
首先,我通过 Python pandas
库将数据集作为数据帧加载。数据集包含 303 条记录、13 个输入要素和 1 个输出类,输出类可以是 0 或 1。
import pandas as pddf = pd.read_csv('source/heart.csv')
df.head()
作者图片
我建立数据集。我定义了两个变量,X
和y
,分别对应于输入和输出。
features = []
for column in df.columns:
if column != 'output':
features.append(column)
X = df[features]
y = df['output']
构建并测试模型
通常,X
和y
被分成两个数据集:训练集和测试集。在scikit-learn
中,这可以通过train_test_split()
函数完成,该函数返回训练和测试数据。然后,通过训练数据拟合模型,并通过测试数据检验其性能。然而,所描述的策略不允许验证模型是否过度拟合。
出于这个原因,我不使用train_test_split()
函数,而是使用 K 折叠交叉验证。
K Folds 将数据集拆分成 k 个子集,在不同的训练集上训练模型 k 次,在不同的测试集上测试模型 k 次。每次,训练集由 k-1 个子集组成,而测试集是剩余的子集。
scikit-learn
库为 K 折叠提供了一个类,称为KFold()
,它接收数字k
作为输入。对于每一对(训练集、测试集),我可以建立模型并计算训练集和测试集的平均绝对误差(MAE)。在这个具体的例子中,我利用了KNeighborsClassifier()
。
from sklearn.model_selection import KFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import mean_absolute_error
import matplotlib.pyplot as pltkf = KFold(n_splits=4)
mae_train = []
mae_test = []
for train_index, test_index in kf.split(X):
X_train, X_test = X.iloc[train_index], X.iloc[test_index]
y_train, y_test = y[train_index], y[test_index] model = KNeighborsClassifier(n_neighbors=2)
model.fit(X_train, y_train)
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
mae_train.append(mean_absolute_error(y_train, y_train_pred))
mae_test.append(mean_absolute_error(y_test, y_test_pred))
然后,我可以绘制培训和测试 MAEs,并对它们进行比较。
folds = range(1, kf.get_n_splits() + 1)
plt.plot(folds, mae_train, 'o-', color='green', label='train')
plt.plot(folds, mae_test, 'o-', color='red', label='test')
plt.legend()
plt.grid()
plt.xlabel('Number of fold')
plt.ylabel('Mean Absolute Error')
plt.show()
作者图片
我注意到,对于所有 k 倍,训练 MAE 非常小(大约 0.2)。相反,测试 MAE 非常大。范围从 0.3 到 0.8。因为训练 MAE 很小,而测试 MAE 很大,所以我可以断定这个模型是过度拟合的。
我将所有之前的操作组合成一个名为test_model()
的函数,它接收模型以及X
和y
变量作为输入。
限制过度拟合
可以通过以下两种策略(潜在地)限制过拟合:
- 降低复杂性
- 调整参数
- 改变模式。
1.降低复杂性
我试图通过将所有输入特征缩放到 0 到 1 之间的范围来改进模型。我利用了由scikit-learn
库提供的MinMaxScaler()
。
from sklearn.preprocessing import MinMaxScaler
import numpy as npfor column in X.columns:
feature = np.array(X[column]).reshape(-1,1)
scaler = MinMaxScaler()
scaler.fit(feature)
feature_scaled = scaler.transform(feature)
X[column] = feature_scaled.reshape(1,-1)[0]
我构建了一个新模型,并调用了test_model()
函数。现在,该模型在训练集和测试集上的性能都有所提高。然而,测试 MAE 仍然很大。因此,模型仍然是过度拟合的。
model = KNeighborsClassifier(n_neighbors=2)
test_model(model, X,y)
作者图片
降低复杂性的另一种可能性是减少特征的数量。这可以通过主成分分析来实现。例如,我可以将输入要素的数量从 13 个减少到 2 个。为此,scikit-learn
库提供了PCA()
类。
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pca.fit(X)
X_pca = pca.transform(X)
X_pca = pd.DataFrame(X_pca)
我在新特性上测试了模型,我注意到模型的性能提高了。现在测试 MAE 的范围从 0.20 到 0.45。
作者图片
2.调整参数
另一种可能性是调整算法参数。scikit-learn
库提供了GridSearchCV()
类,允许搜索特定模型的最佳参数。要调整的参数必须作为dict
传递,对于每个参数,必须传递要分析的值列表。另外,GridSearchCV()
战功也是交叉验证的。在变量best_estimator_
中,最佳估计值在拟合后可用。
from sklearn.model_selection import GridSearchCVmodel = KNeighborsClassifier()param_grid = {
'n_neighbors': np.arange(1,30),
'algorithm' : ['auto', 'ball_tree', 'kd_tree', 'brute'],
'metric' : ['euclidean','manhattan','chebyshev','minkowski']
}grid = GridSearchCV(model, param_grid = param_grid, cv=4)
grid.fit(X, y)
best_estimator = grid.best_estimator_
我测试模型。我注意到测试 MAE 的范围从大约 0.25 到 0.45。
test_model(best_estimator, X,y)
作者图片
3.改变模式
先前的尝试减少了过度拟合。然而,模型性能仍然很差。因此,我试图改变模式。我试一个GaussianNB()
型号。我注意到性能有了惊人的提高。事实上,测试 MAE 的范围在 0.20 和 0.35 之间,因此我可以得出结论,该模型没有过度拟合。
from sklearn.naive_bayes import GaussianNB
model = GaussianNB()
test_model(model, X,y)
作者图片
摘要
在本教程中,我已经说明了如何检查分类模型是否过度拟合。此外,我还提出了三种策略来限制过度拟合:降低复杂性、调整参数和改变模型。
正如这个具体例子中所描述的,我们经常使用错误的模型来处理问题。因此,我的建议是:请尝试不同的型号!
如果你想了解我的研究和其他活动的最新情况,你可以在 Twitter 、 Youtube 和 Github 上关注我。
相关文章
[## Python 和 scikit 中的完整数据分析工作流程-学习
towardsdatascience.com](/a-complete-data-analysis-workflow-in-python-and-scikit-learn-9a77f7c283d3)
来自社区
。
如何自动检查个人资料图片上传
…使用现有的人工智能 API
作者 Gif
https://github.com/JEDS-AI/profile-picture-checker
介绍
个人资料图片上传功能广泛应用于许多应用程序中。它允许用户定制他的简档,并且允许容易地识别他们。在某些用例中,显示一些警告或限制用户上传不合适的图片可能会有所帮助。可能的情况是,上传一张非常模糊或戴着头饰的照片是不允许的/有用的。要实现这样的功能,手动检查图像真的很麻烦。这就是人脸识别可以帮助改进上传个人资料图片的过程的地方。
我将使用 Google Cloud Vision API 来实现这个功能。Google 提供了很多很好用的机器学习 API。将来使用这些端点的成本可能会有所不同,因此如果您感兴趣,请自行查找。现在你有 1000 个免费的初始请求,所以试用是免费的。
设置 Google 云视觉 API
首先,你应该为自己创建一个谷歌云账户。
之后你可以登录谷歌云控制台。
在 Google Cloud 控制台中,您必须执行某些任务才能成功地向 API 发出请求。
为了存档,您还可以使用快速启动设置。
必要的步骤是:
- 创建新项目
- 激活谷歌云视觉 API
- 启用计费(不用担心,有免费方案)
但是真的需要启用,不然不行。 - 设置认证
请随意使用 Google 推荐的方式,使用服务帐户并生成私有和公共密钥。对我来说,生成一个 API 键并在我的请求中使用它要容易得多。但是请记住,它可能不如其他方法安全。根据您的使用情况,保护特定 IP 地址的 API 密钥就足够了。所以如果你只是想尝试 API,一个 API 密匙就足够了。
测试面部识别请求结果
为了测试人脸识别 API,我手工做了一些请求。我用不同的图片进行了测试,看看结果如何变化。请求应该是这样的:
API 键在请求 URL 本身中提供。请求方法是 POST,因为我们想向端点发送一些东西。请求体必须遵循这种给定的格式,因为您也可以在一个请求中发送多个图像。但是我们不会在这里使用这个功能。
您还必须定义应该使用 API 的哪些特性。对于这个用例,它是“面部检测”功能。maxResults 值在这里是不必要的,因为我们只发送一个图像。
对于下面的图片,我希望得到戴头饰的信息。
图片由像素上的 Adrea Piacquadio 拍摄
当成功调用人脸识别 API 时,您会得到如下所示的结果。为了简单起见,我删除了一些数据。例如,你得到了鼻子或眼睛位置的大量数据,但是我们现在不需要这些信息。
如你所见,我们得到了一些关于情绪(喜悦、悲伤、愤怒、惊讶)和图像属性(曝光不足、模糊和头饰)的信息。该值显示了不同参数对于给定图片的可能性。在这个例子中,除了 headwearLikelihood 是“可能”之外,所有参数都是非常不可能的。对于这一结果,如果佩戴头饰不适合上传个人资料图片,则显示一些警告是有意义的。
可能性评级可以有 6 个不同的值:未知、非常不可能、不太可能、可能、可能、非常可能
设置一个基本的 React JS 项目
为了实际使用 API,你可以使用任何可以处理 HTTP 请求的东西。例如,它可以是 Web 应用程序或移动应用程序。我使用 React-JS 创建了一个基本的 Web 应用程序。
你可以去看看 GitHub 仓库,那里提供了我的实现。你可以随意用它来测试你自己的 API。(不要忘记更改 API 键)。
要自己创建一个 react 项目,我建议遵循 React 官方文档的步骤。此外,我安装了 Material UI 作为 UI 框架,这样应用程序开箱后看起来很好。
用例的实现
为了创建一个示例用例,我从实现 3 个组件开始,它们将一起工作来创建 ProfilePictureUploader 组件。
组件包括:
- 图像预览
- 图像警告
- 图像选择
作者图片
试映
ImagePreview 基本上是一个等待图像信息的标签。如果信息被更新,它将重新呈现新的图像。我对高度做了一些限制,并添加了一些额外的造型,使它看起来更好。
警告信息
ImageWarning 组件使用 API 调用的结果,并决定是否显示警告。该组件还获取 API 调用当前是否待定的信息,以显示加载指示符。在这个例子中,我决定在愤怒、模糊或头饰参数不是“非常不可能”时显示警告。如果出现警告,会生成一个小图标和一条文本来通知用户。您当然可以实现其他符合您需求的逻辑。
输入并提交
ImageSelection 组件由一个文件输入和一个提交按钮组成。文件输入用于从用户处获取图像,提交按钮目前没有功能,它只是用来显示如何处理配置文件图像。例如,点击提交,它可以上传到您的服务器。
个人资料图片上传者
这三个组件在一个名为 ProfilePictureUploader 的包装组件中使用,该包装组件提供 API 请求本身并定义其他三个组件的排列方式。
请看看 detectFaces 函数。该函数执行对 Google Cloud Vision API 的请求。如您所见,为了进行人脸检测,需要提供一个请求主体。使用这个请求体,您可以向 https://vision.googleapis.com/v1/images:annotate?的
发送一个 POST 请求 key = $ { APIkey }
API key 就是你从谷歌云控制台得到的 API key。在这里,我只是将它直接写入代码中,这通常不是最好的方法,但在开始时尝试一下也是可以的。请求成功后,将向 ImageWarning 组件发出响应,以确定是否应该显示警告。
结果
作者 Gif
在我的测试中,API 本身非常可靠和快速。它总是花费大约 1 秒钟来得到一个结果,这对于做这样一个复杂的任务来说是相对快的。
一般来说,我认为这是一个很好的方式来改善个人资料图片上传这样的功能,因为它可以帮助减少你的应用程序中不良或不适当的图片数量。无论如何,你应该决定你是否想要完全限制用户上传这样的内容,或者你只是想像我一样显示警告。一如既往,它高度依赖于您的特定用例。
如何选择数据科学专业
在训练营和硕士项目中应该寻找什么,以及各自的优缺点
我有一些数据科学训练营和硕士课程的经验。为了进入这个领域,我参加了一个训练营,并为一个在线训练营和几个硕士项目教过书(现在仍然在教)。
我想分享一些想法,如果我现在选择一个,我会如何考虑这些不同的计划。
数据科学项目的激增
凯拉·法默在 Unsplash 上的照片
数据科学家被 T4 称为 21 世纪最性感的工作已经有很多年了。几年前,公司刚刚开始意识到从数据中结合见解和使用机器学习的潜力。有一个人才争夺战,有合适的技能来帮助这些努力的公司。对数据科学有巨大的需求。
市场反应强烈——很多人想成为数据科学家。为了应对这种需求,训练营应运而生,学术界推出了大量数据科学硕士项目。突然间,数据科学项目无处不在。你如何在它们之间做出选择?
我以前写过关于数据科学项目对谁有用的文章:
很多人试图从自学的角度来研究数据科学,但除非你已经掌握了很多必要的技能,否则一些精心安排的课程和支持会很有帮助。
假设你想做一些培训,在决定合适的项目时,请记住以下几点:
数据科学项目中需要注意的一般事项
- **广度。**数据科学培训项目的最大优势之一是,它让你接触到了许多你原本不会知道的话题。一旦您知道了某个主题的正确关键词,就可以很容易地找到了解它的资源,但是学习数据科学的一个重要方面是至少了解这个多方面学科的情况。确保课程不仅仅是数据争论和机器学习。
- 理论与实践的结合。研究各种机器学习算法的数学是很棒的,但如果你不付诸实践,那就没什么帮助了。同样,如果你没有使用算法的实践经验,学习算法是没有用的。寻找那些强调学习理论和做项目的项目。
- **在非策划数据集上的实践经验。**出于教学目的,给学生一个干净、有条理、没有惊喜的数据集可能很容易。但是这些数据集并不能反映真实世界。寻找那些可以让你获得真实数据集经验的项目,无论是通过他们的作业还是通过自我指导的顶点项目。
- 自定进度?注意一个项目是否是自定进度的是很重要的。你必须足够了解自己,知道自定进度是否适合你——它允许更多的灵活性,但也意味着它将更容易拖延。根据我的经验,完成自定进度计划的学生比那些需要每周承诺的学生少得多。
- 同行。当它是一种社会活动时,学习会容易得多。当你有其他人和你经历同样的过程时,你可以互相学习和鼓励。如果可能的话,强烈倾向于允许与同龄人进行一定程度的社交互动的计划,认识到远程、自定进度计划的灵活性与具有社交成分的计划之间存在权衡。
训练营对大师赛
数据科学主要有两种项目:训练营和学术硕士项目。这里有一些一般性的想法可以帮助你在它们之间做出选择。
训练营
优点
- **倾向于拥有更多最新的课程。**训练营很灵活,往往会不断更新他们的课程。在学术界,每个教师在教学内容上通常有很大的自由,导致质量参差不齐,许多课程没有更新,而训练营往往有更集中的课程,更容易保持最新(可能一开始就创建了更新的课程)。
- **经常有某种形式的工作保证和支持。**虽然训练营可能没有学术机构那样的资源,但他们通常会有更有针对性的职业指导。更好的是,他们中的许多人都有某种工作保障
- 培训倾向于实践方面。通常重点是做——教你如何做的任务,自我驱动的项目,在那里你把你学到的东西放在一起。
缺点
- 一般不是认可的凭证。没有一个训练营真的有如此好的/公认的名字,以至于它们会被认为是你简历上的一个重要凭证。这只会对你的技能有所帮助。
- **未必有深刻的理论成分。**许多训练营掩盖了机器学习/统计理论,支持你快速使用这些工具。不了解您正在使用的工具可能是危险的,并且会限制您对何时使用以及何时不使用某些算法的理解。
- 质量可能有所不同。有了硕士项目,至少你知道提供它的大学的声望。关于训练营,有很多值得怀疑的地方。在承诺任何事情之前,寻找评论。
选择训练营的一些额外建议
- 他们有某种拱顶石吗?作业和课程都很棒,但是一个能让你将所学应用到你所关心的事情中的自我驱动的项目也非常重要。这也给了你一个可以和潜在雇主谈论的项目。
- 他们的工作保障/支持是什么样的?有些项目没有任何工作保障。如果他们不愿意赌你在完成他们的项目后会找到工作,你应该赌吗?
一些有良好声誉的训练营:
这里有几个我认为值得一看的数据科学训练营。做任何决定之前,做你的研究和阅读评论!
- 跳板(有 750 美元折扣的推荐链接):完全披露,我现在已经为跳板辅导了几年。这也是我最喜欢这个项目的原因之一——他们为每个学生安排了一位行业专家作为导师,每周与他进行一对一的通话。他们也有工作保障和广泛的课程。它们是一个自定进度的项目,并且是远程的,所以它确实需要一些纪律来跟上课程并与社区保持联系。
- https://www.thisismetis.com/bootcamps/online-data-science-bootcamp:另一个备受尊敬的训练营。我对他们没有太多的经验,但我听说过他们的课程和工作支持。
- 洞察 :只接受博士学位,被录取者免费。他们有一个很棒的社区,但课程更侧重于拼凑一个演示文稿,这样你就可以开始与潜在的雇主交谈,而不是被结构化。
- 数据孵化器(推荐链接):这是我做的 bootcamp。这让我获得了我的第一份数据科学工作,我学到了很多东西,而且没有花费我任何东西。你可以在这里和这里阅读更多我对这个项目的想法。
硕士学位
优点
- 凭证。无论对错,许多公司仍然将高等学位作为数据科学职位的要求。数据科学硕士学位会让你通过一些要求筛选,通常比训练营更受欢迎。
- 大学资源。与大型教育机构合作有很多好处,可能包括招聘会和职业部门。调查你正在考虑的大学的课程。
缺点
- 贵。与替代方案(训练营或自学)相比,即使是便宜的硕士课程也往往非常昂贵。
- 需要很长时间。硕士课程可能会有灵活的/兼职的选择,但最终,它们往往需要很长时间。这是有充分理由的——一个平衡的、广泛的数据科学教育需要很长时间。但是这确实意味着你将会花更多的时间在训练上,而不是像训练营那样走一条更快的路线。
- 讲师可能没有合适的经验。教授通常要么是没有多少行业经验的学者,要么是没有多少教学经验的行业数据科学家。大学很难找到合适的行业和学术经验的组合来为他们授课。
- 课程可能已经过时。数据科学发展迅速。部分是因为寻找具有最新培训的教师的问题,部分是因为项目主管本身并不总是最新的,学术项目很难教授该领域当前的最佳实践。
选择硕士项目的一些额外建议
- 考虑那些没有被贴上数据科学标签的项目。现代统计学和计算机科学程序通常是数据科学的绝佳入门,并且根据程序可能拥有更高的声望。
- 看使用的编程语言。很容易判断一门课程是否只是他们能找到的导师的大杂烩。确保课程全部(或大部分)用一种语言教授,最好是 Python。如果您需要为每门课程学习一门新语言,您将花费很少的时间学习数据科学,而花费大量时间摸索您不熟悉的编程语言。
- ****它是在一个特定的系里教授,还是跨系教授?不同的部门有不同的长处。跨学科项目通常能够利用不同部门的优势,如计算机科学、统计学、数学和商业。
结论
就是这样!我希望这有助于你选择数据科学项目。
您可能喜欢的其他文章
** [## 为什么大多数数据科学组合项目没有得到招聘经理的认可
towardsdatascience.com](/why-your-data-science-portfolio-project-sucks-208ee830ad1b) **
如何为数据可视化选择正确的颜色
数据即
创建有影响力的图表时,颜色在决策中的作用
本质上,图是由什么构成的?形状,线条,大概吧。肯定是一些文本元素。可能吧。但最重要的是:颜色。无论你选择黑白设计还是彩色设计,任何数据可视化的颜色都会对读者产生不可忽视的影响。
2017 年的一篇名为“可视化中的情感色彩”的研究论文展示了颜色在我们对数据可视化的情感解释上的力量。他们的结果*“展示了如何操纵颜色和调色板属性来实现情感表现力”*。例如,他们演示了轻微改变调色板如何将同一幅图的感觉从“严肃”转变为“有趣”。这只是告诉我们在数据可视化中,我们在颜色方面的选择有多么重要。
在进入问题核心之前,我们先举个例子来说服你。请看下面的两张图表:
作者的图表(基于随机测试数据)
哪一个最吸引你?如果你必须从两个图表中选择一个来说明一篇文章,你会选择哪一个?你可能更喜欢正确的,不是吗?然而,这两张图之间唯一的区别是颜色,仅此而已。
但在第二张图中,我特别注意选择有意义的(根据传达的信息)、一致的(与预定义的颜色代码一致)和容易理解的(特别是对色盲的人)颜色。在我作为数据分析师的整个经历中,我发现这三个要素是成功的数据可视化的关键**。现在让我们进入细节。**
1.让颜色有意义
对于许多决定来说,指导你决定图表颜色的首要问题是:你想传达什么信息?
清楚地陈述你的图表的目标会让你从显而易见的选项开始。正如电影导演比利·怀尔德所建议的:
“对观众来说不要太聪明。显而易见。让细微之处也显而易见。”
谁说数据可视化与电影如此不同?事实上,这就是我们想要通过我们的图表达到的目的:观众立即理解它的含义,并被传达的信息所说服。
例如,如果一个图表显示了两种趋势的相反演变,那么显而易见的选择将是为积极趋势选择一种具有积极内涵的颜色(如绿色),为消极趋势选择一种相反的颜色(如红色)。类似地,渐进演变可以用相同颜色的不同强度变化来表示。
根据你的文化背景以及你希望你的图表传达的感情,选择最有意义的颜色将有助于读者更好地理解和坚持你的图表。如果你想更多地了解用四种不同的方式给同一个图表着色对读者来说会有不同的意义,你可以参考这篇文章:
2.使颜色一致
现在你知道了如何确保你的图表通过所选的颜色传达正确的信息,你必须做出一致的选择。我的意思是:
- 选择有限数量的颜色
- 选择适合环境的颜色
- 一旦设定好,就坚持选择颜色
第一条规则是在一个图表中最多有 10 种不同的颜色,而 T4 倾向于 3 到 5 种不同的颜色。人脑是有局限性的,就像我们的眼睛一样。为了与我们的第一条建议保持一致:如果你想让你的信息清晰有效地传达给观众,避免与多余的信息混淆,比如太多的颜色。
第二,颜色必须符合图表呈现的背景:受众是谁(公众、同事、客户、董事会……)?将在哪种介质上呈现(数字介质,印刷在纸上……)?它将被哪些元素包围(在演示文稿中,在文章中,作为独立的图表…)?同一个图形可以有两组不同的颜色,但是一组比另一组与上下文更相关。
最后,颜色一致性的一个关键要素是坚持为给定的图形定义颜色后选择的颜色。根据我的个人经验,我习惯于为不同的利益相关者构建显示类似数据的仪表板。虽然每个仪表板彼此独立,但观众在查看图形时要习惯于给定的颜色代码,这一点很重要,无论图形显示在哪个仪表板中。让我们举一个首席执行官查看五个不同国家的仪表板的例子:对他们来说,在所有仪表板上有相同的“颜色代码”是最方便、最容易阅读的(例如,“产品 1”将始终显示在深蓝色#337d9e 中,等等)。).
3.使颜色易于使用
正如我们刚才提到的,展示数据可视化的受众和背景对其影响有很大的作用。当你微调颜色选择时,记住上下文。特别是,出现图形的不同设备可以显示不同的颜色变化。为了尽可能避免图形感知上的差异,请避免使用高度饱和的颜色或太浅的颜色,因为它们可能在不同设备上以错误的方式出现。
可达性的另一个方面是考虑有颜色缺陷的人。全球约 8%的男性和 0.5%的女性患有色盲。知道你的观众中有不可忽视的一部分可能是色盲,有一些方法来调整所选择的颜色,以显示所有人都能理解的颜色。一种简单的方法是选择具有不同饱和度值的颜色。此外,您还可以使用色盲模拟器,这是一个免费的在线工具,来测试图形是否是色盲安全的。
如果我们以我最初的例子为例,将两张图传入色盲模拟器,我们会发现右边的图比左边的图更适合色盲人群,因为颜色之间的对比更明显。
使用色盲模拟器显示的作者图形
获胜的组合
根据我的经验,我注意到让漂亮而强大的图表如此成功和令人难忘的是三个被低估的属性的组合:
- 使颜色有意义以使读者立即感觉到你的图形的吸引力
- 使颜色一致,使读者在从一个图形跳到下一个图形时不会迷路
- 使颜色易于使用使所有读者感到关注,并能够获得数据可视化技能的力量
你喜欢读这篇文章吗? 成为 的一员,加入一个不断成长的充满好奇心的社区吧!
如何选择合适的谷歌云平台数据库
向云及更远的地方!我抓住你了,范姆!
坦纳·博瑞克 上 Unsplash
选择正确的 GCP 数据库取决于很多因素,包括您的工作负载和所涉及的架构。今天,我将为大家提供流行的谷歌云数据库服务的概述,包括评估和选择服务时的关键考虑因素。
了解你的数据库
谷歌云平台(GCP)旨在提供一系列计算资源,数据库服务就是其中之一。GCP 有能力处理现代数据,具有高效、灵活和卓越的性能,是一个托管平台解决方案,用于跨地域传播数据。
在选择 Google 数据库服务时,应该考虑很多因素,比如数据的类型和大小、延迟、吞吐量、可伸缩性和 IOPs 等等。
GCP 主要提供三种全球数据分发参考架构模型:
1) 单一— 所有部署模式中最简单的一种,可以通过在 Google 上创建新的云数据库和/或“提升和转移”现有工作负载来部署数据库。
2) 混合— 当云中的应用程序需要访问本地数据库时,这些类型的部署非常有用,反之亦然。
部署混合模型(一些数据在 Google Cloud 上,一些在内部)时,有三个主要因素需要考虑:
主数据库:首先,你需要决定主数据库是存储在本地还是云端。一旦您选择了云,GCP 资源将充当内部资源的数据中心,而如果您选择了内部资源,您的内部资源会将数据同步到云中以供远程使用或备份。
**托管服务:**可用于云中的资源,这些服务包括可伸缩性、冗余和自动备份。但是,您可以选择使用第三方托管服务。
**可移植性:**根据您选择的数据存储类型,您的数据的可移植性也会受到影响。为了确保可靠和一致的数据传输,您需要考虑跨平台存储,如 MySQL。
3) 多云— 这些类型的部署可以帮助您有效地分发您的数据库并创建多个故障保险,因为它使您能够将部署在 Google Cloud 上的数据库与来自其他云提供商的数据库服务相结合,从而为您提供更广泛的专有云功能优势。
部署此模型时,有两个主要因素需要考虑:
集成:确保客户端系统可以无缝地访问数据库,不管它们部署在什么云上,例如,使用开源客户端库使数据库可以跨云顺畅地使用。
迁移:由于有多个云提供商,可能需要借助数据库复制工具或导出/导入流程在云之间迁移数据。Google Storage Transfer service 就是这样一个工具,可以帮助您进行数据库迁移。
云是极限:谷歌云平台数据库服务
GCP 提供了几种数据库服务供您选择。
云 SQL :
Cloud SQL 是一种关系型 GCP 数据库服务,完全由 MySQL、PostgreSQL 和 SQL Server 管理并与之兼容,包括自动备份、数据复制和灾难恢复等功能,以确保高可用性和灵活性。
**何时选择:**从本地 SQL 数据库到云的“提升和转移”,到处理大规模 SQL 数据分析,再到支持 CMS 数据存储和微服务的可扩展性和部署,云 SQL 有许多用途,当您需要关系数据库功能但不需要超过 10TB 的存储容量时,云 SQL 是更好的选择。
云扳手:
另一个完全托管的关系型 Google 云数据库服务 Cloud Spanner 不同于 Cloud SQL,它专注于结合关系型结构和非关系型可伸缩性的优势。它提供了跨行的一致性和高性能操作,并包括内置安全性、自动复制和多语言支持等功能。
**何时选择:**如果您计划使用大量数据(超过 10TB)并需要事务一致性,那么 Cloud Spanner 应该是您的首选。如果您希望使用分片来获得更高的吞吐量和可访问性,这也是一个完美的选择。
大查询:
使用 BigQuery,您可以通过 SQL 和查询流数据来执行数据分析。由于 BigQuery 是一个完全托管的无服务器数据仓库,其内置的数据传输服务可以帮助您从本地资源(包括 Teradata)迁移数据。
它整合了通过 BigQuery ML、BI Engine 和 GIS 提供的机器学习、商业智能和地理空间分析功能。
何时选择:【BigQuery 的用例涉及流程分析和优化、大数据处理和分析、数据仓库现代化、基于机器学习的行为分析和预测。
云大表:
这是一项完全托管的 NoSQL 谷歌云数据库服务,专为大型运营和分析工作负载而设计。云 Bigtable 包括高可用性和零停机配置更改功能。实际上,您可以将它与各种工具集成,包括 Apache 工具和 Google 云服务。
云 Bigtable 用例涵盖金融分析和预测、物联网数据接收、处理和分析,以及超个性化营销应用。
**何时选择:**如果您正在使用大量的单键数据,云 Bigtable 是一个不错的选择,并且更适合低延迟、高吞吐量的工作负载。
云火商店:
Cloud Firestore 是一个完全托管的无服务器 NoSQL GCP 数据库,旨在开发无服务器应用程序,可用于存储、同步和查询 web、移动和物联网应用程序的数据。凭借离线支持、实时同步和内置安全性等关键功能,您甚至可以将 Firestore 与 GCP 的移动开发平台 Firebase 相集成,从而更轻松地创建应用程序。
云 Firestore 用例包括具有在线和离线功能的移动和 web 应用程序、多用户、协作应用程序、实时分析、社交媒体应用程序以及游戏论坛和排行榜。
**何时选择:**当你的重点在于 app 开发,需要实时同步和离线支持的时候。
Firebase 实时数据库:
这是 NoSQL 谷歌云数据库,是 Firebase 平台的一部分。它允许您实时存储和同步数据,并包括离线使用的缓存功能。它还使您能够实现声明性身份验证,通过身份或模式匹配用户。
它包括移动和网络软件开发工具包,以简化应用程序开发。
Firebase 实时数据库的使用案例包括跨设备应用程序的开发、广告优化和个性化以及第三方支付处理。
云存储库:
Cloud Memorystore 旨在实现安全、高可用性和可伸缩性,是一个完全托管的内存 Google Cloud 数据存储,使您能够创建亚毫秒级数据访问延迟的应用程序缓存。
云内存商店的使用案例包括应用程序的“提升和转移”迁移、机器学习应用程序、实时分析、低延迟数据缓存和检索。
**何时选择:**如果您正在使用键值数据集,并且您的主要关注点是事务延迟。
选择关键问题的数据库
我还创建了这个流程图,它可以显示选择数据库的方向:
由 Anuj Syal 创建,异想天开的链接
寻找更多信息
我在 youtube 上制作了这个视频,详细介绍了这个话题
由 Anuj Syal 在谷歌云中选择数据库
我的想法
随着越来越多的企业寻求云服务来运行其核心关键系统,并作为启动其新应用的主要平台,选择正确的谷歌云平台(GCP)数据库开启了可能性,并可以成为交易撮合者,为客户提供最少的停机时间、安全且经济高效的服务和解决方案。
在 Linkedin 和 Twitter 上关注我
如果你对类似的内容感兴趣,点击 Medium 上的“关注”按钮,或者在 Twitter 和 Linkedin 上关注我
如何在组织环境中选择正确的文本分类模型
行业笔记
在应用机器学习中,理解和忽略技术因素的重要性,或者,何时使用推杆走出沙坑。
从沙坑推球(作者的图片)
对于误入沙坑的高尔夫球,典型的反应是咒骂、叹息,然后拿着沙楔跋涉到沙坑。这不是一个艰难的决定。每个高尔夫球袋都有一个沙楔,不像所有其他关于使用哪个球杆的决定——我应该使用 5 号铁杆吗?混血儿?铁木?a 6 铁?沙坑有一个专门为它设计和命名的俱乐部。所以你可能会惊讶地发现,有些严肃的高尔夫专业人士建议,只要有可能,你应该在沙坑里使用推杆。为什么?如果有更好的工具,为什么还要推荐推杆呢?因为最好的工具并不是最适合这项工作的工具,它是你最擅长使用的工具。
如果你从事软件技术方面的工作,你可能经历过一个老工程师兴奋地告诉你他们 15 年前在 awk 中写的某个工具完美地解决了你的某个问题。知道正确的工作使用正确的工具是管理顾问拿这么多钱来提出计划的原因。管理顾问服务没有价值,因为他们是唯一聪明到足以解决难题的人,他们有价值是因为他们见过很多类似的问题,并且他们足够聪明到可以从中吸取教训。你的公司可能会被收购一次,但是三大巨头已经有了几个世纪的合并经验。老工程师的优势不在于他精通命令行工具,也不在于他比初级工程师更聪明,而是他之前已经看到了这个问题。
但是使用 awk 是一个好的解决方案吗?答案很少取决于 awktegenarian 计划的绩效,而更多地取决于当前的组织需求和能力。如果他离开了,或者其他人需要维护或修改程序,或者需要向主管解释程序,使用 awk(一种古老的命令行语言)比电子表格更糟糕,即使电子表格更慢,不能处理那么多数据,并且需要每次手动编辑数据 20 分钟才能使用。
在 Salesforce,我的团队为各种 NLP 任务开发和部署模型,但我们的主要工作是电子邮件的文本分类模型。拟合模型是双重的:您使您的模型适合您的数据和您使您的模型适合您的组织。在这篇文章中,我将从技术数据科学的角度,通过一个示例文本分类问题来说明我们在选择正确的问题模型时学到的一些见解。然后,我将向您展示如何抛弃这一切,以适应您的组织约束。
从技术角度来看,我们选择什么样的模型最终取决于我们的训练数据在多大程度上捕捉到了它将在生产中获得的数据的多样性。Salesforce 拥有大量不同的客户组织。有两个人的组织,也有上万人的组织。他们销售单元、包、许可证和合约。一些公司使用单一、简单的销售流程,另一些公司有几十种不同的渠道来销售各种产品。一些公司比其他公司更有可能允许我们根据他们的数据训练模型。因此,当我们创建数据集时,我们总是知道先验我们的训练数据既不完整又有偏差,这是我们在选择模型时考虑的首要问题。不管我们为手头的任务选择什么模型,它都需要在产品的生命周期中以合理的成本进行部署、扩展和维护。销售人员需要能够向客户演示,产品经理需要能够向高管演示。这些组织需求通常比技术需求更重要。
任务和语料库:
这篇博文的示例任务是将一个句子归类为疑问句/非疑问句。我选择这个是因为这是一个简单的、定义明确的任务,而且我们对问题的定义基本一致。大多数有趣的文本分类任务会涉及到大量的定义争论,比如“我们什么时候一起吃午饭吧”是不是一个调度请求。
对于语料库,我使用的是由杰克·金斯曼准备的数据集。这个数据集对我们的目的特别有用,因为它包含了大量的问题(占句子的 33.81%),这些问题是容易标记的(没有一个遗漏问号),并且许多问题(71.94%的问题)是不合语法的反问句,这给了这个问题实质。(因为我是出于研究目的使用这个语料库,所以数据集的具体内容并不重要,除了有许多带有特殊语法的问题。)有三种基本类型的问题。首先是使用五个 w(19.55%)的 疑问句 ,例如“当巫师和术士透露他们所拥有的东西时,到底发生了什么?”接下来是是-否问题产生是或否的回答(8.51%),比如“它真的来自也门吗?”或者“你会回答吗?”最后是不符合语法的反问句(71.94%),比如“日期公布(早)?”或者“与外国演员合作付款/分散资金?”
因为这个数据集中的所有问题都包含一个问号,所以我通过简单地出现一个结束问号来将每个句子标记为一个问题/不是一个问题。然后,我将数据集分成 80/20,用于训练和测试。因为确定哪种建模方法最适合数据的主要区别归结为“您的问题复杂吗?您的训练数据有多完整?”我操纵数据集来创建不同但相似的上下文,以观察训练数据如何很好地捕捉测试数据的多样性。在第一个数据集中,测试集没有被改动。在第二个数据集中,我从测试数据中删除了所有的问号。在第三个数据集中,我删除了问号,并用一个未知标记(“XXXXX”)屏蔽了测试数据中的五个 W。在第四个数据集中,我只对是非问题(和非问题)进行测试,并且在没有任何是非问题的情况下进行训练。我也从测试数据中去掉问号。在第五个数据集中,我采用了第四个数据集,但也从训练集中删除了问号。下表描述了数据集及其差异。
前期底线:
我对根据您的数据拟合模型的最后建议非常简单。如果你的类与一小部分特性紧密相关,那么使用正则表达式。如果将你的类分开需要更复杂的规则,并且你的训练数据捕获了你的测试数据的多样性,那么使用传统的机器学习,并且作为最后的手段,使用深度学习。当然,数据的“捕获多样性”不是一个精确或可量化的指标,所以我将遍历不同的数据集,并显示随机森林在哪里足够接近(数据集 1、2、3 和 5),以及在哪里不够接近(数据集 4)。下面的流程图总结了这一点:
不探究数据,很难(解读:不可能)知道这些问题的答案,。在某种意义上,您可以使用正则表达式来回答您的类是否可以用一小组功能来划分,因此应该使用正则表达式,您可以使用机器学习来确定您的训练数据是否捕捉到了野外数据的多样性,因此应该使用机器学习。这里的挑战不是技术上的,而是情感上的。一旦你创建了一个模型,尤其是你努力工作的模型,很难删除它。但是过分看重你的模型会阻止你做正确的事情。愿意创造模型,而且要小心谨慎地去做,然后把它们扔掉。你必须愿意谋杀你亲爱的人。
我在某种程度上回避了探索以了解数据的需求,因为我们已经知道了很多关于问题的信息,而不探索这些数据,疑问词形成了一个封闭的类别,并且问题的语法很少出现在问题之外。这有点像开始一个项目,在探索了一个月之后发现它表现得出奇地好,但这是一篇更好的博文,因为我们可以直接进入问题的实质。
从正则表达式开始
如果可以用一小组特性来划分类,那么 RegEx 是最好的方法。如果每个问题都包含一个结束问号,并且结束问号不会出现在文本中的其他地方,那么使用 RegEx 将是完美的。我可以只寻找一个终结问号的存在,但这是一个不切实际的坏的稻草人。请记住,我们已经知道了很多关于问题的知识,如果我们不知道,我们会一直探索数据,直到我们知道,人们并不总是使用问号(例如在随意的谈话,聊天,语法错误等。)并且这些问题倾向于使用五个 W 中的单词。所以我做了两个正则表达式分类器:一个只寻找结尾问号和五个 W,我称之为脆弱正则表达式分类器,另一个做同样的事情,但另外寻找是非问句的句子开始模式,我称之为健壮正则表达式分类器。除了结尾问号之外的附加模式以牺牲精确度为代价提高了召回率。比如句子“我们知道这是什么意思。”是对五个 W 的模式的肯定匹配,但不是一个问题,并且“这是关于病毒还是其他什么”将产生对 Robus 正则表达式分类器的肯定匹配,而不是对脆弱分类器的肯定匹配。这两个正则表达式分类器说明了理解数据的价值。
**
在数据集 1 上,测试数据仍然有问号,两个正则表达式分类器都表现得非常好。在数据集 2 上,测试用例丢失了问号,两个分类器的召回率和精确度都下降了,但没有下降到零,这要归功于除了终端问号之外的附加特征。在数据集 3 上,测试用例缺少问号,问题词被屏蔽,这两个模型在性能上有差异。健壮的正则表达式分类器的召回率进一步下降,因为现在只有是非问题模式会发现问题,是非问题是少数问题,但是脆弱的正则表达式分类器的性能一直下降到零。在数据集 4 和 5 上,健壮的正则表达式分类器再次具有优异的性能。
我们如何改进健壮的正则表达式分类器在数据集 1、4 和 5 上的性能,它在这些数据集上表现良好?由于召回几乎是完美的,我们希望提高精确度,也就是说,找到一种减少误报的方法。这样做的第一个方法是将异常添加到我们的模式中。我反对这样做。
随着您添加异常,您将开始注意到一些异常需要更多的异常,等等。如果你继续沿着这条路走下去,你将会积累严重的技术债务。我最喜欢的论文之一是一篇关于自动断字程序的内存分配的论文。该算法通过规则、例外和例外对例外进行连字符连接,大约有五层深。这种嵌套的 if 语句算法非常强大,速度也非常快,但是众所周知,它很难调试或理解。此外,很容易为新案例添加规则,并且在不了解原因的情况下无意中使您的性能变得更差。正则表达式有一个额外的好处,那就是写起来比读起来容易得多,所以当你创建更多的异常、更细致入微的正则表达式时,你的系统会变得更难理解、更难调试、更难适应新的情况。
正则表达式分类器的性能在数据集 2 和 3 上直线下降,原因很好:正则表达式挑选出的特征不再与我们希望分离的类相关。那么,对此有什么办法呢?我们需要查看数据,并创建更多我们认为可以捕捉差异的模式,但是一旦我们走得太远,模式变得难以管理(主观评估),就该标记数据并让数据决定如何将特征映射到类。即使是最好的正则表达式有时也需要删除。这就把我们带到了下一个方法:机器学习。
开发一个 ML 模型
一旦你开始沿着规则和异常,异常到异常的路径,或者手动调整特性和类分离的路径,就到了机器学习的时候了。如果你发现自己试图实现三个层次的词典排序规则,那么你很早就犯了一个错误,导致你走到了人生的这一步。对于机器学习方法,您需要标记数据,如果您开始制定足够复杂的 RexEx 规则,您可能已经有了一组不错的样本数据。让我们看看随机森林模型在五个数据集上的表现。
ML 模型性能的直觉比 RegEx 分类器简单得多:当训练和测试数据更相似时,模型性能更好。数据集 1、2 和 3 实际上都具有相同的训练数据,并且仅在它们的测试数据上有所偏离,这些测试数据顺序地离训练集越来越远。
从测试集(数据集 2)中删除问号会导致性能明显下降,因为模型关注的主要特征是问号。事实上,问号和句号是两个最重要的特征,而且相差一个数量级。我选择随机森林模型有两个原因:它在各种上下文中表现良好,并且它通过测量每个特性的公开误差来提供特性重要性。像许多事情一样,特征重要性“有点像概率”,但也不尽然——但对于每个特征来说,重要性是一个介于 0 和 1 之间的数字,它们加起来就是一个*。*对于一个重要的特征,通常必须选择在我们的随机森林中对小决策树进行分支,这意味着它既有力地分隔了类别,又相对频繁地出现。如果您最强大的特性在测试集中不经常出现(或者根本不出现),性能就会下降。下面是在五个数据集上训练的随机森林模型的要素重要性表。
所有的模型都需要训练数据在某些重要的方面类似于野外的数据,在这种情况下,重要的是它们被特征化的方式。有两种方法可以将这种关系形象化。第一个是看看在不太重要的特性列表中,你必须深入到什么程度,直到你拥有了出现在大多数测试用例中的特性。**
这个图更容易阅读,但是它掩盖了这样一个事实:随着你对特性的深入研究,它们变得越来越不重要,也就是说,它们出现在更多的测试用例中,但是它们对于划分你的类来说不是很有帮助。我们的特征受制于 Zipf 定律,这意味着这个词的频率与它在频率表中的排名大致成反比。区别性特征很可能不常见。问题识别任务回避了一些问题,因为五个 W 和问号是一个封闭的集合,并且相对频繁地出现,但是尽管如此,排名较低的特征明显不太频繁。为了捕捉这一现象,我做了另一个更难读懂的图,如下:
x 轴是累积的特性重要性,y 轴是包含任何 n 元语法的测试用例的百分比。例如,在数据集 1 中,前两个特征('?“还有“.”)占重要性的 40%多一点,并且出现在几乎每一个测试用例中。ML 模型在数据集 1 上表现良好,因为最重要的特征经常出现在测试用例中。另一方面,数据集 4 说明了几乎相反的情况:大多数重要的特性并没有出现在尽可能多的测试用例中,并且只有当我们进入越来越不有用的特性时,这个百分比才开始上升。
这是你可以用来先验地确定你的训练和测试数据不够相似的东西吗?大概不会。你必须认真仔细地开发模型,确定这个模型不行,然后你必须谋杀你亲爱的模型。每次你都要进入数据。希望这一部分有助于建立你的直觉,理解模型从训练数据的特征化中学到了什么,以及它如何容易地将这种理解应用于测试数据。
缩小差距的一个方法是从你的训练数据中删除信息,以防止过度拟合某些在你的得分数据中不常出现(或从不出现)的特征。数据集 5 与数据集 4 相同,只是在训练数据中没有任何问号。性能显著提高,问号从重要特性列表中消失。如果你不能修改你的数据,试着寻找更多的数据源,最好是那些直接来自或代表你实际评分数据的不同维度的数据源。联系你团队中的其他人或者附近的团队,看看他们是否能想出一些你的模型难以处理的例子。其他团队的人喜欢拿出例子来证明他们比你的模型更聪明。当我在 SlackBot 中提供我们的模型时,我发现我的同事可以想出令人惊讶的反例深度(稍后将详细介绍)。在你刷掉 TensorFlow 之前,试着多找些训练数据。如果你只能做到这些,那就该深度学习了。
作为最后手段的深度学习
你已经得出结论,你的训练数据没有捕捉到你将在野外看到的数据。有各种各样真实的,可以原谅的原因来解释你为什么会沦落到这种境地。也许在收集数据时出现了错误。也许你的 MSA 只覆盖了你的一部分用户,所以你从选择加入的数据中得到一个有偏见的样本。也许你购买了一个类似的数据集,但是它已经过时了,或者不可行。无论你认为你的训练数据没有覆盖野生环境中的数据,以及你无法增加或修复你的数据集的原因是什么,都是时候进行深度学习了。
深度学习非常流行,而我远不是这方面的专家。深度学习似乎可以稳健地处理各种任务,前提是你有足够的数据让它优化大量参数。我尝试了一个简单的双向 LSTM 模型,它做得非常好。
更重要的是,它在所有五个数据集上表现稳健。所以我为什么不推荐你每次只用深度学习,然后收工呢?
如果你还记得,这篇博文是关于如何选择合适的模型。其中一部分意味着选择适合您的数据的模型。另一部分是选择适合您组织的模型。正则表达式在组织环境中有很多优势。它们不需要 GPU 来训练,并且可以作为您已经部署的任何代码的一部分来部署。如果你的主管或经理坚持某个具体的例子有效,你可以确保它有效。如果我们非常诚实的话,正则表达式几乎不需要标签数据的少数正面例子。深度学习模型需要 GPU、大量的标记数据和充足的时间来探索巨大的超参数空间。如果你训练一个深度学习模型,但你的公司以前从未部署过,或者你自己将要部署它,这可能会花费你的项目几个月或几年的时间。您可能更喜欢 F1 分数较低的普通 ML 模型,但是它可以由其他人及时部署和维护。
如果我要告诉你,正确的模型是一个你可以用你所拥有的资源来部署的模型,用你可以得到的数据来训练,在你的老板有耐心的时间内,为什么我要经历所有这些详细的技术分析?如果你试图让一个模型适应组织,而不知道如何首先让它适应数据,你将不会成功。我将分享一些我为 Salesforce 设计签名解析器模型时的例子。
我有三个组织约束,我需要我的模型来适应。第一个是部署模型的团队用 Kotlin 为 Kafka Streams 编写了 jobs。因此,我需要将我的模型打包成一个可部署为 JAR 的库。这意味着我的团队之前使用的两个机器学习框架——ml lib和 TensorFlow 已经过时了。我最终使用了 SMILE (由李海锋编写),因为它在 Scala 中提供了最少的机器学习功能,并自己实现了我的数据科学工作流所缺少的工具。第二个约束是签名解析器需要接受个人身份信息(PII)的训练,但是我们在 Salesforce 的客户数据中不使用 PII。因为签名是* PII,所以我最终编造了训练和测试数据,与我们客户的数据有统计上的相似性,但没有实际使用他们的数据。我在这里写了关于数据伪造的文章。最后,我让标题评分模型作为 Slack Bot 在内部可用,并发现产品经理有几个标题,他们只需需要来查看它的正确评分。理论上,解决这个问题的正确方法是经历标记更多数据和重新训练模型的艰苦过程,但这很耗时,而且还有十几个其他项目更需要我的关注,所以我创建了 Otherwise 模型。我在模型前面放了一个简单的正则表达式,它处理他们需要的特殊情况,否则我的 ML 模型会完成这项工作。*
PS 如果你想知道,这里有一个图表,比较每个模型与每个数据集的 F1 分数。请注意,这里没有一处提到构建新的基础设施和组件来大规模支持 TensorFlow 是非常重要的。
如何为您的数据团队选择正确的结构
现场笔记
在高速发展的初创公司建立数据团队的最佳实践,从雇佣你的第一个数据工程师到 IPO。
关于死亡,莎士比亚的哈姆雷特曾经说过:“ 生存还是毁灭,这是个问题。”
关于她的数据团队,某创业公司一位睿智的数据负责人曾经说过: “集中还是分散,那是个问题。” 而且是很重要的一条。
以下是一些最佳数据领导者如何应用敏捷方法来构建可随公司发展而扩展的数据组织。
随着初创公司越来越多地投资于数据,以推动决策制定并为其数字产品提供支持,数据领导者面临着快速扩展团队的任务。从了解招聘哪些角色(以及何时招聘)到为数据 设置SLA,当今的数据领导者负责——毫不夸张地说——在旅程的每个阶段保持对公司的洞察。
无论您处于这场马拉松的哪个阶段,最大的挑战之一就是为您的数据团队确定合适的报告结构。
随着数据需求的增加,集中式数据团队带来的瓶颈也在增加,分散式数据团队带来的重复和复杂性也在增加。就在你认为你已经找到了“完美”的范例(即,一个中央数据工程团队、分布式数据分析师、一些分析工程师来弥补差距!或者一些数据分析师与在首席技术官手下工作的数据工程师一起向首席运营官汇报工作!),当优先级发生变化时,你的整个策略就会发生变化。
那么,数据领导者应该做些什么呢?
为了更好地了解一些最好的团队是如何解决这个问题的,我与https://www.linkedin.com/in/greg-waldman-a843b130Toast的高级商业智能总监坐下来,讨论他公司数据团队的发展,并分享他在这些集中和分散结构之间永无休止的拉锯战中的经验。
在过去的五年里,Greg 带领 Toast 数据团队从一名分析师(Greg 本人)成长为一个 20 多人的组织,并从集中模式发展为混合分散模式,然后再回来。
请继续阅读,了解 Greg 的团队如何让业务需求驱动数据团队结构,他如何知道何时有必要做出这些改变,以及他希望早点聘用的关键角色。
开始时:当一个小团队努力满足数据需求时
当格雷格在 2016 年加入 Toast 时,该公司已经有 200 名员工,但没有专门的分析人员。尽管缺乏专业人才,但该公司一直优先考虑使用数据来做出决策。
“我们的创始团队非常精明,”格雷格说。“他们用 Excel 文档管理公司,但最终当他们有 200 人时,他们知道这种方法无法扩展。当我来的时候,问题基本上是这样的,“我们有太多的会议,一个人认为数字是 5,而另一个人认为数字是 4,然后他们就一直为此争吵。所以,不要让这种事情发生。"
Greg 立即钻研并开始构建工具、流程和基本的数据程序。第一年,Toast 数据团队增加了两倍,现在有三个人。该公司继续使用数据来推动其文化和决策。
“每个人都说他们有数据驱动的文化,但我在足够多的地方工作过,知道其中的区别,我看到了与吐司相比的并列,”格雷格说。“我们整个公司的人——尤其是我们的领导层——在做出重大决策之前都会认真寻找数据。”
但是,尽管小型数据团队增加了两倍,Toast 本身却增加了一倍。到 2017 年,该公司拥有 400 名员工。集中式数据团队无法满足整个快速增长、数据至上的组织的需求。
“我们在门外排起了长队,”格雷格说。“人们渴望获得比我们所能提供的更多的数据。我认为这对我们来说是一个转折点。因为如果您找不到满足这种需求的方法,那么业务可能会开始以不同的方式运营,并且如果您无法为他们提供必要的数据,那么数据驱动力就会减弱。”
支持作为分散数据操作的超增长
随着各部门开始寻找满足自身数据需求的方法,向分散式结构的转变开始形成。
“最终,公司的其他部门也出现了小规模的分析,比如销售和客户成功,”格雷格说。“主要是因为我们的小团队无法满足不断增长的业务需求。所以他们成立了自己的团队,这种方式很有效!”
2018 年,这个由 10 名数据专业人员组成的分散团队在业务部门内工作,满足了数据需求,并支持了 Toast 的快速发展,因为该公司的规模几乎再次翻了一番,员工人数增长到 750 人。Greg 和他的团队还重建了他们的数据技术堆栈,从端到端数据平台迁移到现代分布式堆栈,包括 s3、Airflow、Snowflake、Stitch 和 Looker。
在其业务部门工作的专职分析师仍然与 Greg 的核心分析团队保持密切联系,这使得 Toast 成为完全集中和完全分散的数据团队结构的混合体。但随着该组织不断扩大规模-2019 年达到 1,250 名员工,拥有 15 名数据分析师、数据科学家和数据工程师-这种混合模式开始出现问题。
数据一致性是一个问题。“当谈到什么是好数据时,整个组织有不同程度的严格性。当你很小的时候,你很好斗,你在成长,任何数据都比没有数据好。但最终,我们认识到不准确的数据可能是有害的。”
即使有技术上准确的数据,Greg 也知道,在建立整个公司的数据可观察性和信任标准时,分析师、技术负责人和下游利益相关者之间的强大沟通是至关重要的。
“随着业务变得越来越大和越来越复杂,你需要分析师开始看到整个业务,”格雷格说。“即使在一个分散的模型中,当涉及到围绕性能和可操作性设置标准时,你也需要确保分析师与其他分析师和技术领导者密切合作。”
重组、重新集中和重新关注数据信任
在评估如何构建他的数据团队时,Toast 总是权衡三种选择:集中式、分散式和混合式,随着时间的推移,他们尝试了每种选择的规模。最终,他发现混合模式对于他的分析团队的规模和范围来说是最有效的。图片由 Greg Waldman 和 Toast 提供。
因此,Toast 将一直在各自的客户成功和走向市场团队下工作的分析师带回到了一个分析保护伞下。
“我们最终实现了集中化,一个讨论过但被低估的好处就是团队中的人们从彼此身上学到了多少东西,”Greg 说。该团队现在是财务和战略部门的一部分。但他知道中央集权的结构可能不是土司的长期解决方案。
“简而言之,我对数据团队的看法是,你希望每个人尽可能多地增加商业价值,”Greg 说。“我们一直非常乐于改变和尝试不同的东西,并理解适用于 200 人、500 人、1000 人和 2000 人的答案是不同的,这没关系。“当你到达那些转折点,需要尝试新事物时,这一点可能会变得有些明显。”
归根结底,无论这对您团队的报告结构意味着什么,都是为了满足业务需求,同时确保技术线索是分析师的推动因素,而不是瓶颈。
扩展创业公司数据团队时要记住的 4 件事
最终,Greg 的团队选定了一个带有少量分布式元素的集中式数据团队结构,为他们提供了对数据产品更大的所有权和治理能力,以及构建可扩展的模块化数据堆栈的能力。图片由 Greg Waldman 和 Toast 提供。
Greg 为在超高速增长的公司中面临类似挑战的数据领导者提供了一些来之不易的建议,但每种策略都回到了他的原则,即专注于哪种方法最符合您公司的业务需求,这可能会随着时间的推移而改变。
简而言之,他建议,领导者应该保持敏捷,团队应该愿意适应业务需求。以下是方法。
雇用数据通才,而不是专家,但有一个例外
Greg 认为,你应该雇佣的第一个专家是数据工程师。
Greg 说:“早期,我们基本上只是雇佣了能做一点点事情的数据运动员。“我们让这些运动员扮演分析师/数据工程师。我有一个高级经理的职位空缺,一个数据工程师申请了,但她对管理没有任何兴趣。当我和她交谈时,很明显我们团队非常需要专门的数据工程技能。回想起来,考虑到我们的增长轨迹,我应该在一年前就寻找这样的人。”
很多时候,数据团队会因为缺乏构建和维护 ETL 管道所需的技术支持而束手束脚,并确保底层的数据基础设施能够根据公司的分析需求进行扩展。
“因此,尽管我仍然相信应该雇佣那些什么都能做的数据运动员,但数据工程师是个例外。在你雇佣了几个分析师之后,你的第一个数据工程师应该紧随其后。”
从第一天开始就优先考虑建立一个多样化的数据团队
这是不言而喻的,但是当涉及到为长期成功建立你的团队时,你需要(早期)投资于具有不同经历和背景的候选人。同质化是创新的阻碍,它阻碍了数据分析师和工程师理解所有数据消费者的观点和需求。
然而,当你大规模快速行动时,可能很难记住这一点——除非你制定了一套反映这一目标的清晰的招聘和增长 KPI。
格雷格说:“尽早考虑多样性。“因为特别是在这些小型数据团队中,如果你不小心,你最终只会和一群来自相似背景的志同道合的人在一起。你不想要一群相同的人——你需要不同的视角。”
说‘我们需要建立一个多元化的团队’是一回事,但要做到这一点完全是另一回事。那么,数据领导者应该如何入门呢?
这里有几个小技巧:
- 与高管和你的人员团队合作,撰写包含不同经历和背景的工作描述(例如,避免使用过于男性化的语言,使用中性语言)
- 将不同的招聘小组放在一起(即使他们不是从数据团队中挑选出来的),以体现你正在努力建立的团队
- 广撒网,招聘可能没有传统数据头衔或角色的候选人;这是一个不断发展的空间!
- 实施不分性别或种族的申请流程,根据资格和经验进行筛选
“在创业旅程的后期,建立一个多元化的团队要困难得多,因为来自不同背景的人希望加入一个由不同背景的人组成的团队。如果你一开始就没有考虑到这一点,事情会变得更具挑战性。”
过度沟通是变革管理的关键
这一点在我们“远程优先”的世界中更加重要,在这个世界中,许多团队在家里工作,通过电子邮件、Slack 和信鸽(开玩笑!)是任何工作的必要组成部分。
红点风险投资公司(red point Ventures)的董事总经理托马斯·通古兹(Tomasz Tunguz)表示,公司应该始终如一地向客户重复自己的 (即他们的核心价值主张),即使这看起来没有必要。当涉及到与数据利益相关者交流他们的工作和任何团队变化时,数据领导者也是如此。
例如,如果你的分散的客户成功分析师在客户成功主管手下工作 3 个月后将向分析主管汇报,你不仅应该传达这种变化正在发生,而且还应该重申这种调整不会改变你的团队产出的性质。即使团队不再分散,涉众仍然可以期望映射到核心业务目标的准确、及时的分析。
虽然结构变化不可避免地会影响利益相关者(职能团队)和服务提供者(数据团队)之间的关系性质,但是整理、交流和重复这种转变如何不会影响您团队的 KPI 将会恢复善意并帮助跨职能团队克服变化。
格雷格说:“如果你让分析师向企业领导人汇报,确保他们有权根据他们看到的数据进行反击。”“否则,这可能是一种微妙的动态,鼓励他们展示支持轶事假设的数据。当你将这些团队重新纳入分析体系时,你的分析师们将相互学习,但影响其他部门可能会很有挑战性。”
最近,Toast 一直在运行一个很大程度上集中的分析模型,该模型表现良好,满足了过去一年半的业务需求。
不要高估“单一的真理来源”
“单一真实来源”或黄金数据的概念是一个强大的概念——理由很充分。努力实现指标一致性和一致的干净数据有助于公司相信他们的数据为他们指明了正确的方向。尽管如此,作为一个超增长创业公司的数据领导者,你会在任何给定的时间参与大量的实验和项目——只要你有对数据信任的方向性https://www.montecarlodata.com/data-observability-the-next-frontier-of-data-engineering/(即,这张表是最新的吗?我知道谁拥有这个数据集吗?为什么 50 排变成了 500 排?),对“单一真相来源”的需求就没有那么迫切了。
“我总是告诉人们不要高估整个‘单一来源的真相’的概念,”格雷格说。“作为一个完美主义者,我花了很长时间才学会这个。有时候你需要做到 100%正确,但也有很多时候你做不到。通常,方向的准确性是好的,而你试图做到完美只会浪费资源。80/20 法则是关键。”
数据总是杂乱的,很少是完美的。如果您优先考虑端到端的数据健康和准确性视图,而不是更精细的控制,您将完成更多工作。
Greg 给数据领导者的最后一条建议?
“雇佣沟通能力强的优秀人才,其他一切都会变得容易得多。优秀的人会带你找到其他优秀的人,你可以雇佣世界上最聪明的人,但如果他们不能把自己的分析传达给不太懂技术的人,他们就不会成功。”
想了解更多关于建立成功数据团队的信息?伸出手去 巴尔摩西 和 蒙特卡洛团队 。
python 中如何对手写数字进行分类
没有任何机器学习库的帮助
如果你已经阅读了本系列的前几篇文章(页面底部的链接),你应该已经完全从基本原理构建了一个 DNN 类。让我们看看是否可以使用这个类来创建一个能够读取手写数字的神经网络。
这是一个经典的例子,说明对于我们人类来说很容易做到的事情,但是要编写一个程序来完成同样的任务却非常困难。在我们人类对图片进行分类的情况下,让我们想想正在发生什么。对于观看图像的人来说,大脑接收光子形式的输入,并基于该输入对图像进行分类。
基于此,我们可以说,击中我们眼睛的光子和图片的内容之间一定有某种关系。很明显,对吧?当然,图片看起来是什么样子和图片是关于什么的有关系。但是,数学建模需要这个命题;
根据我们从图片中接收到的输入(光子),存在某种数学函数可以告诉我们图片中有什么。
使用神经网络,我们将很容易找到这个极其复杂的函数。
获取和清理我们的数据
本着推进人工智能的精神,修改后的国家标准与技术研究所(MNIST)收集了数以万计的手写数字照片,每张照片都有一个标签。这个数据可以在这里下载。下面是其中一个数字的例子。
*此图标注为 a 3。*图片作者
现在,对于我们人类来说,我们接收光子进入眼睛的输入。类似地,对计算机来说,这张图片只是像素值的矩阵。这些像素值的范围从 0 到 255(因为图像是黑白的),如下所示:
图片作者
这些图片是 28X28,784 像素值。我们的目标是将这些 784 像素的值映射到所写的数字。那么,我们开始吧。我们先来看数据。你应该已经从我上面提供的 Kaggle 链接下载了一个 zip 文件夹。解压缩文件夹后,您会看到一个 mnist_test 和 mnist_train CSV 文件。目前,我们将只关注 mnist_train CSV。下面我用 pandas 打开文件,然后显示文件的内容。
**import pandas as pd
import numpy as np
import matplotlib.pyplot as plt****data = pd.read_csv(‘mnist_train.csv’)**
图片作者
如您所见,该数据的第一列是标签(图像表示的数字),其余是图像的像素值(总共 785 列)。每一行都是一个单独的图像。使用 pandas iloc 功能,我们可以将输入与标签分开。此外,我们确保输入在 0 和 1 之间正常化。
**labels = np.array(data.iloc[:,0])
x_train = np.array(data.iloc[:,1:])/255
# We divide by 255 so that all inputs are between 0 and 1**
我们的下一步可能看起来很奇怪,但却是至关重要的。现在每个标签只是一个数字或一维。这意味着神经网络必须输出 0 到 9 之间的正确数字。我们可以通过将输出的维度增加到 10 个维度,每个维度对应一个数字,来使我们的神经网络的分类任务变得更容易。例如,我们将更改标签“0”,使其为“[1,0,0,0,0,0,0,0,0,0],’ 1’ = '[0,1,0,0,0,0,0,0,0]等等。这被称为“一热编码”,我这样做我们的标签如下。
**encoded_labels = []
for i in range(len(labels)):
naked = [0,0,0,0,0,0,0,0,0,0]
naked[labels[i]] = 1
encoded_labels.append(naked)**
现在我们可以使用 matplotlib 来检查这些图像实际上是什么样子。
**# Take a look at what the images look like
random_index = np.random.randint(0,40000)
img = x_train[random_index].reshape(28,28)
plt.imshow(img, cmap = “gray”)**
正如你所看到的,我们的神经网络真的有它的工作要做,用这些图片…
图片作者
创造我们的神经网络和训练
我们将使用在本文之前创建的 DNN 类(在这里找到)。每个图像有 784 个输入和 10 个输出,我将选择一个有 1250 个神经元的隐藏层。因此,我们的层应该是[784,1250,10]。在 for 循环中,我们简单地生成一个随机索引,然后对与该索引对应的数据和标签运行 train 函数。我还每 1000 步打印一些有用的信息,见下文:
**model = DNN([784,1250,10])****from collections import deque
error = deque(maxlen = 1000)
"""A deque is just a list that stays at 1000 units long (last item gets deleted when a new item gets added when at length = 1000)"""****for n in range(30000):
index = np.random.randint(0,59998)
error.append(model.train(x_train[index], encoded_labels[index]))
if n%1000 == 0:
print(“\nStep: “,n)
print(“Average Error: “, sum(error)/1000)
plt.imshow(x_train[index].reshape(28,28), cmap = “gray”)
plt.show()
print(“Prediction: “, np.argmax(model.predict(x_train[index])))**
结果和测试
在我的电脑上仅仅过了 5 分钟,神经网络就能正确识别大多数数字。10 分钟后,神经网络似乎已经完全训练完毕,平均误差达到 0.2 左右。重要的是不要过度训练模型,这会导致神经网络只是记忆图像,这将使它在预测它从未见过的事物方面非常糟糕。
让我们使用我们下载的那个 mnist_test.csv 文件来看看我们的神经网络对它以前从未见过的数据执行得有多好。下面我对 mnist_test 文件中的每张图片调用 predict 函数,然后检查预测是否正确。然后我计算这个神经网络正确预测的百分比。
**test_data = pd.read_csv(‘mnist_test.csv’)
test_labels = np.array(test_data.iloc[:,0])
x_test = np.array(test_data.iloc[:,1:])/255****correct = 0****for i in range(len(test_data)):
prediction = np.argmax(model.predict(x_test[i]))
if prediction == test_labels[i]:
correct +=1****percent_correct = correct/len(test_data) * 100
print(percent_correct,’%’)**
以下是该项目的最终代码:
我最后得了 93.5 分。随意尝试训练更长的时间,增加层数和/或神经元数,改变激活函数或损失函数,改变学习速率,看看这是否可以改善。虽然 93.5%非常令人兴奋,但我们实际上可以做得更好。我们可以让神经网络能够识别图片中的独特特征,以帮助它识别图像。这是卷积神经网络背后的思想,我将在以后的文章中详细解释。
感谢您的阅读!如果这篇文章在某种程度上帮助了你,或者你有什么意见或问题,请在下面留下回复,让我知道!此外,如果你注意到我在某个地方犯了错误,或者我可以解释得更清楚一些,那么如果你能通过回复让我知道,我会很感激。
这是一系列文章的继续,这些文章从头开始对神经网络进行了直观的解释。其他文章请参见下面的链接:
第 5 部分:如何用 python 对手写数字进行分类
如何用 SQL、Tableau 和 Google 搜索清理地理地名
实践教程、数据工程、数据清理、SQL 和 Tableau
使用熟悉的工具检测和清理不干净的地理数据
“垃圾进,垃圾出。”匿名的
介绍
任何数据工程、数据分析和数据科学项目的生命周期都包括数据清理过程。清理数据的主要目的是检测和纠正损坏、不准确或不完整的数据记录。此外,有效的清理有助于确保数据分析或数据科学产品完整准确地传达所需信息。
最近在一家大型企业任职时,我在 Tableau 中开发了一个员工差旅分析仪表板。我使用 SQL 从旅行请求和管理系统的 IBM DB2 数据库中获取数据。
每个旅行请求包括目的地城市、州或省(如果适用)和国家,以及许多数据元素。不幸的是,差旅申请 web 表单没有对这些字段执行任何编辑检查,因此差旅申请人拼错了许多地名,并用不正确的地理位置填充了应用程序的数据库记录。
由于 travel analytics 仪表盘每周更新一次,我需要一个简单易行的流程来清理每周新引入的地理数据错误。我开发的方法包括使用 Tableau 来识别地理地名错误,使用 Google 和 Wikipedia 来确定正确的和确认的值,使用 SQL 来检索和清理数据。
本文描述了我用来清理地理数据的方法的修订版。它通过一个小规模项目展示了该解决方案,包括一个示例数据库表、SQL 代码和一个 Tableau 数据可视化项目。
样本数据清理项目概述
地理地名数据清理项目样本包括以下步骤和组成部分:
- 使用 SQL SELECT 语句从数据库表中检索美国城市人口数据。我在这个示例项目中使用了 Microsoft SQL Server,但是它可以与任何关系数据库管理系统一起工作,比如 Oracle、MySQL、PostgreSQL 等。
- 将使用 SQL 检索的城市人口数据加载到 Tableau 工作表中。
- 创建城市及其人口的地图。Tableau 将自动检测并报告无效的城市名或州代码。换句话说,Tableau 将识别其内部地理地名数据库中不存在的城市名称和州代码。
- 对于无效的地名,使用谷歌搜索找到正确的拼写位置。此外,如有必要,使用维基百科来确认城市名称、州代码和人口值的组合。
- 在上述步骤 1 中描述的 SQL 语句中添加或修改 CASE 语句,以更正拼写错误的城市名称和州代码。
- 将使用修改后的 SQL 语句检索到的城市人口数据重新加载到 Tableau 工作表中。
- 查看城市人口地图。如果仍然不准确,重复步骤 4 到 7,直到 SQL 语句清除了所有脏数据。
"我们相信上帝,所有其他人都会带来数据."爱德华·戴明
城市人口数据库表示例
为了演示数据清理技术,我创建了一个名为 City_Population 的表,其中包含以下几列:
- 城市 —城市的名字
- 州代码 —州的双字符代码
- 人口——2020 年美国人口普查人口或维基百科记录的 2010 年后的最新估计人口
城市 _ 人口表结构。图片作者。
然后我用 17 行填充了这个表,其中充满了数据错误,如下所示。
City_Population 表中的示例数据。图片作者。
基本 SQL 选择查询
下面显示的选择查询检索 City_Population 表中所有行的 City、State_Code 和 Population 值。请注意,由于 Population 是 SQL Server 中的一个关键字,因此它被放在了方括号中。
选择查询以获取城市、州代码和人口。作者代码。
将数据加载到 Tableau
在我以前的职位上,我直接从 Tableau Desktop 调用 SQL 查询,将 SQL Server 和其他数据库中的数据加载到 Tableau 项目中。对于这个项目,我使用 Tableau Public,它排除了调用 SQL 查询的能力。Tableau Public 支持各种其他数据源。这个项目我选了 Excel。以下是将数据加载到 Excel,然后再加载到 Tableau Public 的一般步骤:
- 在 SQL Server Management Studio (SSMS)中运行选择查询。如果运行 SQL Server,可以使用 SSMS。否则,请使用您所使用的数据库的查询工具。
- 将查询返回的数据复制并粘贴到 Excel 工作表中。保存 Excel 工作簿。
- 打开 Tableau Public(或 Tableau Desktop)并将 Excel 文件添加为数据源。
按照以下步骤从 SSMS 输出窗口复制数据。
将数据从 SSMS 复制到 Excel。图片由作者提供。
下面是 Excel 电子表格,其中包括从 SSMS 粘贴的数据。注意,工作表名为 city_population_dirty,工作簿名为 city_population_dirty.xlsx,我将这个工作表加载到 Tableau 中。稍后,我将加载一个“干净”的工作表到 Tableau 中。
Excel 中的数据,并准备加载到 Tableau。图片由作者提供。
要将数据加载到 Tableau 中,请打开 Tableau Public 或 Tableau Desktop。接下来,在连接标题下,单击[Microsoft Excel]。当提示打开文件时,导航到 city_population_dirty.xlsx 并单击[打开]。
连接到 Tableau Public 中的 Excel 电子表格。图片由作者提供。
肮脏城市的人口数据应该加载到 Tableau 中,如下所示。
已加载到 Tableau Public 中的脏城市人口数据。图片由作者提供。
查看 Tableau 中的脏数据
将数据加载到 Tableau 后,我在一个名为“Population Dirty”的工作表中创建了一个地图。注意屏幕右下角的信息“10 未知”。这一信息表明,Tableau 无法绘制数据中的 10 个地名。
城市人口图。请注意,名称无效的城市不会显示在地图上。图片由作者提供。
要识别脏数据,请单击“10 未知”Tableau 将显示如下所示的编辑位置对话框。
请注意未识别的城市名称,例如 Aims 和 Amerillo 。我可以用下拉框中的值(位于“未识别”下)替换这些值。但是,虽然这样做会清除此 Tableau 仪表板的数据,但清除的数据将无法用于其他 Tableau 项目或其他用途。因此,对于本文描述的项目,我决定清理 SQL 中的数据。然后,清理后的数据将可供所有下游用户使用,比如 Tableau。
Tableau 公共“编辑位置”对话框显示无效或无法识别的城市名称。图片由作者提供。
在谷歌中查找正确的城市名称
谷歌搜索使用微软在其 Visual Studio 工具的智能感知中使用的技术,在用户输入文本时找到可能的结果。此外,谷歌似乎会纠正拼写,甚至可能使用“听起来像”的算法来识别搜索词。
对于无法识别的城市“Aims”,我查看了 Excel 文件中的数据,并注意到具有脏值的记录的州代码是“IA”因此,当我搜索“Aims ia”时,Google 返回“Ames,ia”和“City in Iowa”作为第一个结果。我确信“Ames”是“Aims”的正确拼法,于是继续前往下一个拼错的城市。
在谷歌中搜索城市和州。图片由作者提供。
但如果不确定谷歌是否返回了正确的城市,我也会在维基百科上查找谷歌建议的地方的拼写。例如,当我在谷歌中搜索“查尔斯顿南卡罗来纳州”,它会返回“查尔斯顿南卡罗来纳州的一个城市”为了验证这一点,我在维基百科中查找了这个城市,并将其人口与 Excel 电子表格中的人口进行了比较。两个源中的值都是 150,277。
在维基百科中确认城市人口。图片由作者提供。
清除 SQL 中的数据
为了清理 SQL 中的地名,我在 SELECT 查询中使用了 CASE 语句。例如,下面显示的查询更正了十个城市名。它还将明尼苏达州的州代码从“MP”更新为“MN”
查询以获取和清除城市、州和人口数据。作者代码。
为了从 Tableau 的查询中准备数据,我运行它并将其输出数据复制到名为“city_population_clean.xslx”的工作簿中名为“city_population_clean”的 Excel 工作表中,如下所示。
Excel 电子表格与清洁城市人口数据。图片由作者提供。
在 Tableau 中加载和查看清洁城市人口数据
接下来,我将干净的数据集加载到 Tableau 中,并基于干净的数据构建一个地图工作表。该过程与上面针对脏数据描述的过程相同。
请注意,工作表不再在右下角显示类似“10 不干净”的消息。这是因为 Tableau 可以识别输入文件中的所有地名。此外,它还在地图上标出了每个城市。
Tableau Public 地图,展示了精选美国城市的完整列表。图片由作者提供。
最后一步是将 Tableau 项目的“干净”工作表保存到 Tableau 公共服务器。你可以在这里查看。
Tableau 公共仪表板称为美国城市人口选择。图片由作者提供。
这种数据清理方法的利与弊
虽然这里介绍的数据清理方法成功地清理了城市人口表中的地名,但是与其他方法相比,它有一些优点和缺点。
赞成的意见
- 过程很简单。
- 可以快速检测并纠正脏数据。
- 当最终用户或软件很少将脏数据引入数据库表时,这种方法是实用的(只需对 SQL 查询进行少量更改)。
骗局
- 需要 SQL 编码技能,以潜在地改变每个新数据集的 SQL 查询。
- 容易出错,因为每当检测到脏数据时,代码都需要更改。即使一个优秀的程序员也可能犯错误。
- SQL 代码可能会变得难以处理。最终,SQL 查询可能包含数百行,使得维护变得困难。
替代清洁方法
虽然上面描述的数据清理过程提供了一个实用的解决方案,但是您也可以考虑其他解决方案。例如,在一个理想的系统中,当请求旅行的员工输入数据时,web 表单会检测并纠正数据错误。这种方法将通过消除大多数地理数据清理需求来节省时间和金钱。
另一种数据清理方法涉及一个将脏地名映射到干净地名的表。SQL 查询将用干净的地名替换从城市人口表中检索到的脏值。
结论
这里描述的地理数据清理方法在维护旅行分析仪表板方面证明是有效的。即使每周有数百条新的旅行记录,获取、清理和发布这些数据的整个过程也只用了不到一个小时。
我希望这些关于数据清理的信息对您有所帮助。对我来说,数据清理是数据工程、数据分析和数据科学项目生命周期中最具挑战性和最令人满意的步骤之一。
“没有数据就进行理论化是一个严重的错误。”—夏洛克·福尔摩斯
工具信息
如何清理文本数据
…删除数据科学应用的停用词
JESHOOTS.COM在 Unsplash 上的照片【1】。
目录
- 介绍
- 清理文本数据
- 摘要
- 参考
介绍
数据大部分时间都是杂乱的、无组织的、难以处理的,这应该不足为奇。当您从教育实践进入数据科学时,您会发现大多数数据是从多个来源、多个查询获得的,这可能会导致一些不干净的数据。在某些或大多数情况下,您必须提供最终用于训练模型的数据集。有一些文章关注数字数据,但是我希望这篇文章主要关注文本数据,这与自然语言处理相一致。也就是说,这里有一个在 Python 中清理文本数据的简单方法,以及它什么时候有用。我将使用来自 TMBDF 5000 电影数据集【2】的流行数据集,这样你就可以跟上了。
清理文本数据
Marylou Fortier 在Unsplash【3】上的照片。
删除停止字
另一种解释“停用词”的方法是删除不必要的文本。但是,需要注意的是,当您使用常用停用词库时,您可能会删除实际上想要保留的单词。这就是为什么你应该先考虑你想删除的单词列表。常用的停用词有‘the’
、‘of’
等。你想要删除这些词的原因是如果你想保留这些词、短语、句子等的主题。一个例子是*‘有一次他们在七月去商店参加节日聚会’*。如果你去掉停止词和一些不必要的词,你只会得到剩余的time, July, holiday, party
。
话虽如此,让我们看看如何从电影片名中删除一些停用词:
import pandas as pdimport nltk.corpus
nltk.download(‘stopwords’)
from nltk.corpus import stopwordsdf = pd.read_csv('...path/tmdb_5000_movies.csv')stop_words = stopwords.words('english')
df['clean_title'] = df['title'].apply(lambda x: ' '.join([word for word in x.split() if word not in (stop_words)]))
在上面的代码中,我们导入必要的库,然后将我们的数据读入 pandas 数据帧。从那里,我们分配我们将从‘title’
列的文本中删除的停用词,这将在‘clean_title’
列中显示它们各自的效果。输出如下所示。在第 1、3 和 8 行中,是停用词被删除的地方,正如您可以并排看到的 before 和 after。
作者截图[4]
除了 nltk 的停用词库,您还可以“手动”添加其他停用词。为了实现这个功能,你可以简单地给stop_words
添加一个字符串列表。例如,如果我们想要删除文本“3”,因为在这种情况下它不是一个数字,我们可以将它以及单词“at”和字母“v”添加到列表中。它的工作方式如下:
stop_words = stopwords.words(‘english’) + [‘At’, ‘v’, ‘3’]# apply the same code as above but assign
# a new column to see the differencesdf['clean_title_v2'] = df['title'].apply(lambda x: ' '.join([word for word in x.split() if word not in (stop_words)]))
在下面的屏幕截图中,您可以看到 lambda 函数是如何移除添加的字符串列表中的值的。
作者截图[5]。
现在我们已经展示了一种清理文本数据的方法,让我们讨论一下这个过程对数据科学家有用的可能应用:
- 删除不必要的单词,以便您可以执行词干分析,在词干分析中,您可以隔离删除后留下的单词的词根
- 与上面类似,你可以只分离出单词的词条
- 只有保留必要的单词才能让您更容易地标记数据中的词性,例如,如果您只标记形容词,并在您的模型数据中使用该文本,如“美丽”、“惊人”、“响亮”将用于预测电影评论的目标变量。一个模型将能够更容易地从形容词中识别情感,以辨别电影评论是好是坏,或者电影需要改进什么
- 从更新文本的主要词创建一个摘要仪表板,例如,去掉“蜘蛛侠 1”、“蜘蛛侠 2”和“蜘蛛侠 3”中的数字,将允许对所有蜘蛛侠电影进行分析,如赚钱,或这些电影的平均评论评级
- 更容易进行主题建模——在大量文本之间找到共同的主题
- 创建更少量的文本,以便您的建模在训练和预测时变得更快、更便宜
- 可用于删除错误的文本,例如,如果人们正在手动键入响应,您可以清理他们的响应,如果他们的输入是从语音到文本的,您可以自动删除通常被语音错误解释的单词
当然有更多的理由删除停用词,并清理你的文本数据。同样重要的是要记住,有一些新兴的算法可以很好地处理文本数据,比如 CatBoost。
摘要
正如你所看到的,仅仅清理数据的一部分就可以为进一步清理和处理数据打下基础。希望数据的这种变化最终会使您的模型更加健壮和准确。我给出的例子很小,但你可以看到如何将它应用到包含数百个句子的数据中会更有用。
总而言之,以下是如何从文本数据中删除停用词:
* import libraris* import your dataset* remove stop words from the main library* add individual stop words that are unique to your use case
更新: 单词 *The*
没有被删除,因为它是大写的,所以在清理它之前,请确保将所有文本都小写。感谢您的标注, 米亚罗姆 !
我希望你觉得我的文章既有趣又有用。如果你同意这种删除停用词的方法,请在下面随意评论——为什么或为什么不?你喜欢不同的图书馆吗?如果你有,请随意评论你喜欢其中一个的原因。这个图书馆有什么缺点?你知道一个更新的库可以在效率、易用性和速度方面击败 nltk 吗?还有哪些清理文本数据的方法?你是否碰巧根本不使用库,而只是删除了你管理的一个特定列表?谢谢你看我的文章!
请随时查看我的个人资料和其他文章, Matt Przybyla ,也可以在 LinkedIn 上联系我。
参考
[1]照片由JESHOOTS.COM在Unsplash(2019)上拍摄
[2] Kaggle, TMBDF 5000 电影数据集,(2021 —已访问)
[3]Marylou Fortier 在 Unsplash 上拍摄的照片,(2020)
[4] M.Przybyla,清洁文本示例,(2021 年)
[5] M.Przybyla,清理文本示例并添加个别停用词,(2021 年)