TowardsDataScience 博客中文翻译 2020(五百二十七)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

基于卷积神经网络和自动编码器的图像超分辨率

原文:https://towardsdatascience.com/image-super-resolution-using-convolution-neural-networks-and-auto-encoders-28c9eceadf90?source=collection_archive---------8-----------------------

深度学习提升图像质量指南!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(来源)

问题陈述挺熟悉的。你们可能都在某个时候遇到过图像失真的问题,因此会试图提高图像质量。嗯,由于深度学习技术的进步,我们将尝试通过训练卷积神经网络和使用自动编码器来提高图像的分辨率!

先决条件

  1. 基本了解卷积神经网络(CNN)
  2. TensorFlow、Keras 和其他一些强制性 python 库的工作。

什么是自动编码器?

自动编码器是一种用于无监督学习的生成模型。

通俗地说,可以说这些模型获取一些输入 x ,试图学习一些潜在特征,然后在这些学习到的特征的帮助下重构输入 x 以给出一些期望的输出 X

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这里,图像输入被重建(源)

我们将使用自动编码器模型的概念来增加图像的分辨率。关于自动编码器的详细了解,点击 这里

实施:

库导入

让我们打开 Jupyter 笔记本,导入一些需要的库。

import numpy as np
import cv2
import glob
import tensorflow as tf
from tensorflow.keras import Model, Input, regularizers
from tensorflow.keras.layers import Dense, Conv2D, MaxPool2D, UpSampling2D, Add, Dropout
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from keras.preprocessing import image
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split 
import pickle

下载数据集

我们将在野生家园 数据集中对 标记的人脸进行处理。该数据集包含标记人脸的数据库,通常用于人脸识别和检测。然而,我们的目的不是检测人脸,而是建立一个模型来提高图像分辨率。

点击此处 下载数据集。

数据集由多个子目录组成,这些子目录包含该人的各种图像。因此,从这些目录中捕获图像路径非常重要。

face_images = glob.glob('lfw/lfw/**/*.jpg') #returns path of images
print(len(face_images)) #contains 13243 images

加载并预处理图像

原始图像的尺寸为 250 x 250 像素。然而,在普通计算机上处理这些图像需要很大的计算能力。因此,我们将把所有图像的尺寸缩小到 80 x 80 像素。

由于大约有 13,000 张图像,如果我们单独处理它们,将会花费很多时间。因此,我们利用 python 中提供的 多处理 库来简化执行。

tqdm 是一个进度库,我们用它来获得工作完成的进度条。

from tqdm import tqdm
from multiprocessing import Poolprogress = tqdm(total= len(face_images), position=0)
def read(path):
  img = image.load_img(path, target_size=(80,80,3))
  img = image.img_to_array(img)
  img = img/255.
  progress.update(1)
  return imgp = Pool(10)
img_array = p.map(read, face_images)

为了将来节省时间,让我们在 pickle 库的帮助下存储我们的 img_array (包含图像):

with open('img_array.pickle','wb') as f:
  pickle.dump(img_array, f)print(len(img_array))

模型训练的数据准备

现在,我们将把数据集分成训练集和验证集。我们将使用训练数据来训练我们的模型,验证数据将用于评估模型。

all_images = np.array(img_array)#Split test and train data. all_images will be our output images
train_x, val_x = train_test_split(all_images, random_state = 32, test_size=0.2)

由于这是一个图像分辨率增强任务,我们将扭曲我们的图像,并把它作为一个输入图像。原始图像将被添加为我们的输出图像。

#now we will make input images by lowering resolution without changing the size
def pixalate_image(image, scale_percent = 40):
  width = int(image.shape[1] * scale_percent / 100)
  height = int(image.shape[0] * scale_percent / 100)
  dim = (width, height) small_image = cv2.resize(image, dim, interpolation = cv2.INTER_AREA)

  # scale back to original size
  width = int(small_image.shape[1] * 100 / scale_percent)
  height = int(small_image.shape[0] * 100 / scale_percent)
  dim = (width, height) low_res_image = cv2.resize(small_image, dim, interpolation =  cv2.INTER_AREA) return low_res_image

我们的想法是将这些扭曲的图像输入到我们的模型中,让模型学会恢复原始图像。

train_x_px = []for i in range(train_x.shape[0]):
  temp = pixalate_image(train_x[i,:,:,:])
  train_x_px.append(temp)train_x_px = np.array(train_x_px)   #Distorted images# get low resolution images for the validation set
val_x_px = []for i in range(val_x.shape[0]):
  temp = pixalate_image(val_x[i,:,:,:])
  val_x_px.append(temp)val_x_px = np.array(val_x_px)     #Distorted images

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

输入图像

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

原象

模型构建

让我们定义模型的结构。此外,为了克服过度拟合的可能性,我们在卷积层中使用了 l1 正则化技术。

Input_img = Input(shape=(80, 80, 3))  

#encoding architecture
x1 = Conv2D(64, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(10e-10))(Input_img)
x2 = Conv2D(64, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(10e-10))(x1)
x3 = MaxPool2D(padding='same')(x2)x4 = Conv2D(128, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(10e-10))(x3)
x5 = Conv2D(128, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(10e-10))(x4)
x6 = MaxPool2D(padding='same')(x5)encoded = Conv2D(256, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(10e-10))(x6)
#encoded = Conv2D(64, (3, 3), activation='relu', padding='same')(x2)# decoding architecture
x7 = UpSampling2D()(encoded)
x8 = Conv2D(128, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(10e-10))(x7)
x9 = Conv2D(128, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(10e-10))(x8)
x10 = Add()([x5, x9])x11 = UpSampling2D()(x10)
x12 = Conv2D(64, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(10e-10))(x11)
x13 = Conv2D(64, (3, 3), activation='relu', padding='same', kernel_regularizer=regularizers.l1(10e-10))(x12)
x14 = Add()([x2, x13])# x3 = UpSampling2D((2, 2))(x3)
# x2 = Conv2D(128, (3, 3), activation='relu', padding='same')(x3)
# x1 = Conv2D(256, (3, 3), activation='relu', padding='same')(x2)
decoded = Conv2D(3, (3, 3), padding='same',activation='relu', kernel_regularizer=regularizers.l1(10e-10))(x14)autoencoder = Model(Input_img, decoded)
autoencoder.compile(optimizer='adam', loss='mse', metrics=['accuracy'])

您可以根据自己的选择和要求修改该模型,以获得更好的结果。你也可以改变层数、单位数或一些正则化技术。暂时先往前走,看看我们的模型是什么样子的!

autoencoder.summary()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

模型摘要的屏幕截图

模特培训

我们将首先定义一些回调,以便将来模型可视化和评估变得容易。

early_stopper = EarlyStopping(monitor='val_loss', min_delta=0.01, patience=50, verbose=1, mode='min')model_checkpoint =  ModelCheckpoint('superResolution_checkpoint3.h5', save_best_only = True)

让我们训练我们的模型:

history = autoencoder.fit(train_x_px,train_x,
            epochs=500,
            validation_data=(val_x_px, val_x),
            callbacks=[early_stopper, model_checkpoint])

在 12GBNVIDIATesla K80**GPU 上,每个纪元的执行时间约为 21 秒。**65 世达到早期停止。

现在,让我们在测试数据集上评估我们的模型:

results = autoencoder.evaluate(val_x_px, val_x)
print('val_loss, val_accuracy', results)

val_loss,val _ accuracy[0.002111185426451,0.265356767

我们从我们的模型中得到了一些非常好的结果,大约 93%的验证准确性和 0.0021 的验证损失。

做出预测

predictions = autoencoder.predict(val_x_px)n = 4
plt.figure(figsize= (20,10))for i in range(n):
  ax = plt.subplot(3, n, i+1)
  plt.imshow(val_x_px[i+20])
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False) ax = plt.subplot(3, n, i+1+n)
  plt.imshow(predictions[i+20])
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False)plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

第一行—输入图像,第二行—输出图像

结尾注释

在这个故事中,我们学习了自动编码器的基本功能,并实现了一个图像超分辨率增强任务。这项任务在日常生活中可能有多个用例。例如,我们也可以使用这种技术来提高低分辨率视频的质量。因此,即使没有标签,我们也可以利用图像数据解决一些现实世界的问题。

如果您有任何其他使用案例或技术来处理图像数据,并且如果您发现了更多改进的图像增强模型,请在下面的响应块中分享!

这篇文章的全部代码可以在 这里 找到。

参考

  1. Snehan Kekre 在 Coursera 上的一门课程。

使用 Javascript 进行图像放大

原文:https://towardsdatascience.com/image-upscaling-with-javascript-836445267496?source=collection_archive---------48-----------------------

实践教程

我最近发布了一个工具,upscaler js,它可以用 Javascript 在你的浏览器中放大图片,并将图片尺寸缩小 1/16。它的设计是与模型无关的——你可以即插即用任何可以转换为 Tensorflow.js 的训练过的模型

在这篇文章中,我想展示我认为的浏览器中神经网络的一个杀手级用例,以及我如何发现这项研究,将其转换为 Javascript,以及未来改进它的方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

https://upscaler.ai //作者动画

假设你在做一个电子商务平台。你的用户上传产品照片来销售。

你设计了一个看起来很棒的网站,用来突出你的用户手工制作的美丽和奇妙的产品。只有一个问题——一旦你启动,你发现你的用户正在上传小的像素化的图片,突然之间你美丽的网站看起来不那么漂亮了。

(我是从经验中得出的结论——这种情况在我身上发生过不止一次。)

你可以回头向用户唠叨要更好的图像——有时这是可行的。但通常情况下,他们所能得到的只有他们提供的图片。也许图像是从 pdf 截屏的,或者也许图像是旧的,用户没有更好的。即使他们有更好的图像,让你的用户回去帮你修改他们的图像也是一件费力的事情,即使这是为了他们的利益。

有没有我们可以探索的技术解决方案?当然有,它叫做超分辨率

你所说的“超级分辨率”是什么?

假设有人上传了一张 150 像素的照片到我们的电子商务网站:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

merec0 的快乐狗

我们想在我们的主页上展示这张图片,因为它是一只漂亮的狗,但我们的设计要求图片为 300 像素。我们能做什么?如果我们将每个像素加倍,我们会得到看起来像素化的更大图像:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过复制像素放大图像

你必须努力在浏览器中实现像素化的外观;默认情况下,大多数浏览器会对图像应用某种缩放算法,通常是双三次插值,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用双三次插值放大图像。

使用双三次插值放大的图像看起来肯定没有第一幅图像像素化,我敢打赌大多数人会觉得它更有美感,但它很模糊,没有人会误认为是高分辨率图像。

**超分辨率是一种机器学习技术,用于从较低分辨率的图像重建较高分辨率的图像。**你可以把这个过程想象成在图像中绘制新像素,实现比双三次插值算法更高的保真度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 GAN 放大图像。

许多不同的方法可以用来实现超分辨率,也有一些很棒的博客文章描述了基本的理论这里这里

超分辨率通常使用 Python 在后端实现。以这种方式建造它有很好的理由。在后台运行它可以让你接触到强大的硬件,而这些硬件可以让你使用最新、最精确的模型。如果获得最高分辨率的图像很重要,后端部署是一个不错的选择。此外,许多用例是“一次缩放,经常显示”——如果放大一幅图像需要更长的时间,没什么大不了的。

另一方面,在后端实现这一点也有缺点。一个是即时反馈——你需要将图像上传到服务器,进行处理,然后发送回来,这可能需要一段时间,取决于你的用户连接和你的模型大小。这可能不是小事,特别是因为如此多的前沿实现处于最前沿,具有不稳定的依赖性和不断变化的需求。而且,如果您的部署需要 GPU,这可能会成为一个昂贵的提议,并且难以扩展。

事实证明,我们可以在浏览器中运行,这样做有一些明显的好处。

第一,部署问题?完全消失了。用 Javascript 运行神经网络意味着不需要安装任何东西,不需要配置任何 GPU——tensor flow . js 会处理所有这些事情。模型直接在用户的浏览器中运行。

其次,你的用户会看到更多即时反馈。特别是对于带宽可能较慢的连接,如电话,直接在设备上执行推理可以省去昂贵的往返步骤。

第三,也是我认为最有说服力的论点——你可以提供更小的图片。有时候,小得多的图像。例如,上面的那些图片?300px 是 724kb。150px 版本?是 9kb 。这是一张原始文件大小的百分之六的图像*。这是一个巨大的减少!*

当然,在浏览器中运行有一些明显的缺点。最大的问题是你受到用户硬件的限制。这体现在两个方面。一个是,如果你想部署最新最棒的型号,你可能就要倒霉了。特别是如果他们是 GPU 饥饿,他们只是可能无法在浏览器中运行。近年来,包括苹果和谷歌在内的硬件制造商已经投入了巨额资金来提高他们的设备上芯片的性能,特别关注提高在设备上运行神经网络的能力。好消息是,年复一年,这项技术的性能会越来越好;坏消息是,对于使用旧设备的用户来说,性能差异将变得更加显著。如果您想要跨平台的一致体验,服务器端解决方案可能是更好的选择。

最终,尽管精确的权衡将取决于用例,但 Javascript 绝对是考虑该技术应用的一个有价值的竞争者。让我们看看如何评估那里有什么,看看什么对我们的目的有用。

通过小道消息听到的

如果你来自 Javascript 世界,你脑海中的一个问题是——你最初是怎么听说这项研究的?

大多数前沿的机器学习研究都张贴在 arxiv.org 的网站上,在那里可以免费搜索和下载 PDF 格式的研究成果。这是学术研究,论文可能倾向于理论和数学,很难理解。这可以吓跑很多人——一开始当然是把我吓跑了。

我不想低估充分理解研究的重要性——深入理解理论通常可以带来与你的领域相关的新见解和发展——但你不一定需要对使用它的技术有深刻的理解。特别是如果你专注于推理,就像我们在这种情况下,你可以依靠他人来评估研究,以及实现训练代码,在某些情况下,提供训练模型。

有一个网站就是这么做的,叫做论文,代码:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

https://paperswithcode.com截图

研究按主题领域分类,并根据其相对于公认指标的表现进行排名。甚至有一个专门针对这个领域的特定类别

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

https://paperswithcode.com 的截图

您可以根据标准数据集查看每个实现的性能,并查看如何根据不同的指标对它们进行测量。PSNR 和 SSIM 是测量超分辨率任务性能的两种常用方法; PSNR 可以测量噪声, SSIM 测量两幅图像的相似度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来自“图像间相似性度量方法快速概述”

指标可能有点棘手。你可以在上面的图像中看到,相同的 PSNR 分数可以有完全不同的 SSIM 分数,具有相应不同的视觉表现。

PSNR 和 SSIM 都是衡量一幅图像彼此差异的标准,但都不能代替人类的评价。作为人类,我们感知图像的方式与计算机不同。比如说,饱和度不同但也更清晰的一组像素可能导致较低的度量分数,但从人的角度来看更美观的分数。

SR 算法通常由几种广泛使用的失真度量来评估,例如 PSNR 和 SSIM。然而,这些度量从根本上与人类观察者的主观评价不一致。感知质量评估采用非参考指标,包括马评分和 NIQE,两者均用于计算 SR 挑战赛中的感知指数。在最近的一项研究中,Blau 等人发现失真和感知质量是相互矛盾的。— 王等

除了判断模型准确性的主观性,准确性不是我们最关心的还有其他原因。记住,我们的最终目标是一个用 Javascript 运行的模型。考虑以下因素也很重要:

  • 一篇好论文。我们想要一个健康的建筑。我们可能需要对基础理论有所了解,所以论文清晰易懂、严谨是很重要的;一篇论文被引用的频率也可以很好地反映其整体质量。
  • 性能良好。速度和准确性一样重要。运行一分钟的模型不适合浏览器。
  • 可保存,可转换。实现的模型必须与 Javascript 兼容。我们将很快触及细节,但最重要的是坚持 Tensorflow 实现,因为 Tensorflow.js 是在浏览器中进行机器学习的主要方式,所以 Pytorch 实现是不可能的。

我最终选择了 ESRGAN

我开始看按分数排序的论文。一些得分较高的实现要么没有链接的代码实现,要么代码实现完全在 Pytorch 中。(并不是所有的代码实现都会在 paperswithcode.com 上展示,所以自己去谷歌一下是个好主意。)

ESRGAN 在指标上排名很高,并在 Tensorflow 中实现了很多。这篇论文本身相当清晰易懂。ESRGAN 基于以前的架构, SRGAN ,它本身是一个健壮的架构,但 ESRGAN 进行了许多改进,包括改进了生成器的构建模块,改进了预测图像显示逼真程度的鉴别器,以及更有效的感知损失。

在我能找到的实现中,我觉得有三个满足了我的标准,看起来代码质量不错,文档也不错。

如果不下载并运行代码,很难确定一个实现是否适合。如果你习惯于安装一个npm库并直接进入,请做好准备:使用机器学习代码通常是一种沮丧的练习。解决依赖性挑战、环境问题和内存瓶颈可能会将评估变成一件多天的事情。

出于这个原因,包含Dockerfile s 或 Google Colab 链接的回购通常是一个非常好的迹象。这也是一个好迹象,当作者包括预训练的重量,以及这些重量是如何训练的文件。如果您能够直接跳到推论,它有助于更快地评估模型;同样,关于如何训练这些权重的信息使您能够测试自己的实现,这为您提供了一个坚实的基准。在回购中忽略这些不会破坏交易,但会让你的日子更难过。

不管作者是否提供 Dockerfile,我通常会建立自己的docker file,因为当我探索 repo 时,我会安装自己的依赖项并编写探索性代码,我希望能够以可复制的方式运行这些代码。几乎在每一种情况下,当我玩了几个星期的机器学习代码后,当我回来时,我会遇到一些深奥的错误,这些错误是由一些包过时或升级引起的。固定您的版本,从一开始就获得一个可复制的环境!

我最终选定了由 idealo 实现。代码易于阅读,提供了预先训练的模型,作者提供了他们探索太空之旅的精彩记录。然而,真正的关键是我只需要做一些修改就可以将 RDN 模型转换成 Javascript。转换 RRDN 模型有点棘手——稍后会详细介绍。

转换为 Javascript

Tensorflow.js 提供了一个方便的命令行工具,用于将模型转换为 Javascript,称为 TFJS converter。您可以使用类似下面的内容来转换模型:

tensorflowjs_converter --input_format=keras --output_format=tfjs_layers_model ./rdn-model.h5 rdn-tfjs

我已经整合了一个谷歌实验室来证明这一点。

为了将模型干净地转换成 Javascript,需要注意一些事情:

  1. 模型必须以 Keras 或与 Tensorflow 转换器兼容的其他格式保存。此外,确保将模型转换成 Javascript,而不仅仅是权重。如果是后者,您可能会收到一个含糊不清的错误,没有任何关于正在发生什么的指导。
  2. 变量不能引用self——这让我对 idealo 的实现产生了误解。(参考本 Github 问题或我的 PR ,寻求解决方案)
  3. 所有张量运算都必须用 Javascript 实现。除了试错法,我不知道还有什么更好的方法来检查这个问题(也就是转换模型,看看它是否能运行)。
  4. 如果实现了自定义层,则必须用 Javascript 重新实现。例如,RRDN 模型的定制层必须重新实现,以便干净地保存。在这篇文章的后面,我将讨论如何处理自定义层。
  5. 在 Tensorflow.js 转换器的输出中,我必须手动将模型的class_nameFunctional更改为Model。(在 Google Colab 中,这是实现这个的单元格。)不知道为什么会这样,也不知道是不是 bug 欢迎评论!
  6. 图像的任何预处理和后处理都需要用 Javascript 再现。

拉你的体重,好神经元

性能是基于浏览器的应用程序的关键。更瘦的模特表现更好。

有两种方法可以提高 Javascript 的性能。

首先,我们可以量化我们的模型。量化模型意味着降低模型权重的精度。这可能会导致较低的准确性,但是可以显著减小模型的大小(并且具有使模型比 gzip 更可压缩的附带好处)。

我们可以在 tensorflow js 转换器中直接量化:

tensorflowjs_converter \
   --input_format tfjs_layers_model \
   --output_format tfjs_layers_model \
   --quantize_uint8 \
   original_model/model.json
   quantized_model/

在这种特定情况下,最大量化量uint8,对最终模型的性能没有显著影响。

第二,我们可以修剪我们的模型。修剪是我们在训练中剔除表现不佳的权重的过程。我还没有亲自探索过这条途径,但是如果你感兴趣的话你可以在这里阅读更多相关内容。对于在前端挤出额外的性能来说,这无疑是一个很有前途的策略。

浏览器中的推理—给我看看代码!

我们已经转换并量化了 RDN 模型。成功!现在,我们如何让它在浏览器中运行?我们可以用以下内容加载我们的模型:

import * as tf from "@tensorflow/tfjs";
tf.loadLayersModel("./rdn-tfjs/model.json");

确保你加载的是model.json而不是bin文件。

然后,我们可以得到作为张量的图像:

const img = new Image();
img.crossOrigin = "anonymous";
img.src = "your-image";
img.onload = () => {
  const tensor = tf.browser.fromPixels(img).expandDims(0);
};

张量是几乎所有神经网络中使用的一种数字数据结构,你可以在这里阅读更多关于它们的内容。

在上面的代码中需要注意两件事:

  1. 如果你正在处理来自其他领域的图像,你可能会遇到 CORS 问题。将crossOrigin设置为anonymous会有所帮助。
  2. 你需要调用expandDims从你的图像中获取的张量。你需要给你的模型传递一个四维张量;要了解更多原因,你可以点击这里查看我关于图像分类的文章。

现在我们有了一个张量,我们可以在模型中运行它:

import tensorAsBase64 from 'tensor-as-base64';
const prediction = model.predict(tensor).squeeze();

还有维奥拉。你有一个升级的张量,准备在你的浏览器中显示!

下面是 CodeSandbox 上所有代码实现:

这仍然需要一段时间——在我的例子中,大约 2.5 秒——这对于生产来说是不可接受的。此外,它还有一个令人讨厌的副作用,就是在工作时冻结了用户界面。让我们来看一些不同的提高性能的策略。

热身

Tensorflow.js 中神经网络的初始调用将花费很长时间,但是随后的调用将会快得多。

TensorFlow.js 通过运行 WebGL 着色器程序在 GPU 上执行操作。当用户要求执行操作时,这些着色器被缓慢地组装和编译。着色器的编译发生在 CPU 的主线程上,可能会很慢。TensorFlow.js 将自动缓存已编译的着色器,从而使第二次调用具有相同形状的输入和输出张量的相同操作的速度快得多。— Tensorflow.js 文档

我们可以利用这一点,通过传递一个虚拟张量来“预热”我们的模型。这里有一些你可以使用的代码(查看 CodeSandbox 上的代码):

const dummyTensor = tf.zeros([1, img.height, img.width, 3]);
model.predict(dummyTensor);

在这种情况下,我的推理时间下降到 150 毫秒。好多了!然而,这只有在张量大小完全匹配的情况下才有效。我们显然不能依赖这个——用户可以上传任何大小和比例的照片。此外,当模型运行其预测时,用户界面上仍有明显的滞后。

让我们先试着解决第二个问题。如果我们把计算从主线程转移到一个网络工作者身上会怎么样?

网络工作者

这里有一个 CodeSandbox 链接,演示了 Web Workers 的使用。(这个例子使用了 UpscalerJS,而不是手工写出 TFJS 代码,但是概念是一样的。)

将代码转移到 web worker 可以让我们将处理从主线程中转移出来,从而让我们以更流畅的速度运行动画。然而,它不是万灵药;动画中仍有一些起伏。我相信这种波动来自 GPU 本身锁定线程,这在旧设备上比新设备上表现得更糟。网络工作者绝对有帮助,但他们不能完全解决问题。

将图像分割成块

如果我们不是一次处理完整的图像,而是将图像细分为多个部分分别处理,会怎么样?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者制作的动画

如果我们将图像细分成几个部分,我们可以将一个长任务分成 4 个任务,每个任务之后我们可以释放 UI 线程:

const tensor = tf.browser.fromPixels(img);
const [height, width] = tensor.shape;
for (let i = 0; i < 2; i++) {
  for (let j = 0; j < 2; j++) {
    const slicedTensor = tensor.slice(
      [(i * height) / 2, (j * width) / 2],
      [height / 2, width / 2]
    );
    const prediction = model.predict(slicedTensor.expandDims(0)).squeeze();
  }
}

这里有一个 CodeSandbox 链接演示这个

这极大地提高了我们代码的响应能力,但现在又出现了一个新问题:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者制作的动画

这些放大的图像往往在边缘有伪像。这是许多放大算法中固有的一个相当常见的问题,但它通常不是一个问题,除非你密切关注放大图像的边缘。然而,在这种情况下——因为我们将许多图像拼接成一幅图像——问题就更加明显了。

修复方法是给我们的每个图像切片添加填充——类似这样:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者制作的动画

然后我们可以切掉多余的像素,组合成一幅没有任何伪像的图像。这里有一个代码沙箱,演示了端到端的

最好的一点是,只要你把补丁的大小设置得足够小——比你期望得到的最小图像小——你就能得到大小一致的图像。还记得我们在预热部分提到的要求图像大小一致以获得速度提升的好处吗?这个解决方案双管齐下!

RRDN 和寻找定制层

到目前为止,我们一直在处理 RDN 模型。RRDN 模型是更强大的版本,它依赖于定制层,需要用 Javascript 重新实现。

我在 Tensorflow.js 中没有找到大量关于自定义图层的文档。有官方文档,还有蔡的这个要点,这是我能找到的大部分内容。

Python 中的两个自定义层定义为:

class PixelShuffle(tf.keras.layers.Layer):
    def __init__(self, scale, *args, **kwargs):
        super(PixelShuffle, self).__init__(*args, **kwargs)
        self.scale = scale

    def call(self, x):
        return tf.nn.depth_to_space(x, block_size=self.scale, data_format='NHWC')

    def get_config(self):
        config = super().get_config().copy()
        config.update({
            'scale': self.scale,
        })
        return config

class MultiplyBeta(tf.keras.layers.Layer):
    def __init__(self, beta, *args, **kwargs):
        super(MultiplyBeta, self).__init__(*args, **kwargs)
        self.beta = beta

    def call(self, x, **kwargs):
        return x * self.beta

    def get_config(self):
        config = super().get_config().copy()
        config.update({
            'beta': self.beta,
        })
        return config

在 Javascript 中,这些看起来像:

class MultiplyBeta extends tf.layers.Layer {
  beta: number;

  constructor() {
    super({});
    this.beta = BETA;
  }

  call(inputs: Inputs) {
    return tf.mul(getInput(inputs), this.beta);
  }

  static className = 'MultiplyBeta';
}

class PixelShuffle extends tf.layers.Layer {
  scale: number;

  constructor() {
    super({});
    this.scale = SCALE;
  }

  computeOutputShape(inputShape: number[]) {
    return [inputShape[0], inputShape[1], inputShape[2], 3];
  }

  call(inputs: Inputs) {
    return tf.depthToSpace(getInput(inputs), this.scale, 'NHWC');
  }

  static className = 'PixelShuffle';
}

您还需要显式注册每个自定义层:

tf.serialization.registerClass(MultiplyBeta);
tf.serialization.registerClass(PixelShuffle);

这里需要指出一些事情:

  • 确保您在层上定义了一个静态的className,它与层的名称完全匹配
  • call是您进行大量计算的地方。
  • computeOutputShape相信你只需要定义它是否不同,这个函数被调用来告诉 TFJS 你的输出张量的形状
  • 你可能需要把函数调用从 Python 翻译成 Javascript 例如,Python 中的tf.nn.depth_to_space变成了 Javascript 中的tf.depthToSpace

训练您的模型

超分辨率技术的一个挑战是它们的规模是固定的。

这意味着,一个经过训练可以将图像放大 2 倍的模型,将无法放大 3 倍或 4 倍。它只能将图像放大到 2 倍。

要改变规模,你需要从头开始训练一个模型。你可以想象,支持不同的规模可以大大增加你必须做的训练量。

此外,有一些迹象表明,针对特定数据集的进一步培训会产生与您的领域相关的特定益处。

首先,我们表明,较大的数据集导致更好的面向 PSNR 的方法的性能。我们使用一个大模型,其中 23 个残差中残差块(RRDB)放置在上采样层之前,随后是两个卷积层用于重建…一个广泛使用的训练数据集是 DIV2K,包含 800 个图像。我们还探索了其他具有更多样化场景的数据集——Flickr 2K 数据集,由 Flickr 网站上收集的 2650 张 2K 高分辨率图像组成。据观察,具有 DIV2K 和 Flickr2K 的合并数据集,即 DF2K 数据集,提高了 PSNR 性能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来自 ESRGAN paper

针对特定领域的数据集进行训练可能会提高准确性。

去年,我花了一些时间和 RAISR 一起工作。该论文中的一个关键见解是,压缩低分辨率图像会产生一个更具弹性的模型,能够更好地处理伪像,而锐化高分辨率图像会产生更具美感的放大图像(代价是相对于度量标准而言性能更差)。我怀疑——虽然我不确定——类似的技术可能在这里的训练中产生类似的好处,我目前正在试验寻找答案。

升级。射流研究…

我已经将所有这些打包成一个名为 Upscaler.js 的 npm 模型。

它不知道正在使用的升级模型,这意味着在未来,我将能够改进模型,并可能引入适应各种用例(人脸、插图)的模型。我目前通过 JS CDNs 服务模型,并期待在未来增加更多的模型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者制作的动画

我认为有很多改进的机会,特别是在性能方面,但坦白地说,我很高兴这是可能的。

想象一下能够将此应用于视频流。想象一下,如果您能以普通视频流的形式提供文件大小为 6%的视频,会怎么样?我们还没有到那一步——我们必须将工作速度提高 10 倍才能处理实时视频——但是离已经不远了。想想真的很令人兴奋!

使用 Google Colab 在 Python 中将图像和蒙版分割成多个部分

原文:https://towardsdatascience.com/images-and-masks-splitting-into-multiple-pieces-in-python-with-google-colab-2f6b2ddcb322?source=collection_archive---------10-----------------------

图像和蒙版分割成更小部分的实际例子

数据标注者使用特殊的标注工具来标注对象。例如,计算机视觉标注工具(CVAT) 在计算机视觉领域广为人知。自然,贴标机使用高分辨率图像会更方便。当您需要标记大量对象时尤其如此。

在我参与的一个屋顶分割任务中,需要突出屋顶的三角形段、四边形段、其他段和边缘。下图显示了此类标记的一个示例(白色表示边,红色表示三角形,绿色表示四边形,蓝色表示其他多边形):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图像由 Oleksii Sheremet 使用 matplotlib 模块创建

原始图像是从谷歌地球获得的,像素为 2048x1208。数据标签员用 CVAT 以同样的分辨率对掩膜进行了标注。为了训练模型,图像和蒙版应该采用较低的分辨率(从 128x128 到 512x512 像素)。众所周知,图像分割是一种最常用于将大图像分割成较小部分的技术。因此,合理的解决方案是将图像及其对应的蒙版分割成具有相同分辨率的部分。

所有用于拆分的代码都是在 Google Colab 中实现的。让我们仔细看看。导入库:

import os
import sys
import shutil
import glob
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from PIL import Image

将 Google Drive(包含图片和蒙版)安装到 Google Colab:

from google.colab import drive
drive.mount('/content/gdrive')
%cd "gdrive/My Drive/File Folder"

一个用于创建新目录和递归删除现有目录内容的有用函数:

def dir_create(path):
    if (os.path.exists(path)) and (os.listdir(path) != []):
        shutil.rmtree(path)
        os.makedirs(path)
    if not os.path.exists(path):
        os.makedirs(path)

覆盖原始图像的裁剪功能被调整到原始图像限制,并包含原始像素:

def crop(input_file, height, width):
    img = Image.open(input_file)
    img_width, img_height = img.size
    for i in range(img_height//height):
        for j in range(img_width//width):
            box = (j*width, i*height, (j+1)*width, (i+1)*height)
            yield img.crop(box)

将图像和蒙版分割成较小部分的功能(裁剪窗口的高度和宽度以及起始数字作为输入参数):

def split(inp_img_dir, inp_msk_dir, out_dir, height, width, 
          start_num):
    image_dir = os.path.join(out_dir, 'images')
    mask_dir = os.path.join(out_dir, 'masks')
    dir_create(out_dir)
    dir_create(image_dir)
    dir_create(mask_dir)
    img_list = [f for f in
                os.listdir(inp_img_dir)
                if os.path.isfile(os.path.join(inp_img_dir, f))]
    file_num = 0
    for infile in img_list:
        infile_path = os.path.join(inp_img_dir, infile)
        for k, piece in enumerate(crop(infile_path,
                                       height, width), start_num):
            img = Image.new('RGB', (height, width), 255)
            img.paste(piece)
            img_path = os.path.join(image_dir, 
                                    infile.split('.')[0]+ '_'
                                    + str(k).zfill(5) + '.png')
            img.save(img_path)
        infile_path = os.path.join(inp_msk_dir,
                                   infile.split('.')[0] + '.png')
        for k, piece in enumerate(crop(infile_path,
                                       height, width), start_num):
            msk = Image.new('RGB', (height, width), 255)
            msk.paste(piece)
            msk_path = os.path.join(mask_dir,
                                    infile.split('.')[0] + '_'
                                    + str(k).zfill(5) + '.png')
            msk.save(msk_path)
        file_num += 1
        sys.stdout.write("\rFile %s was processed." % file_num)
        sys.stdout.flush()

让我们设置必要的变量:

inp_img_dir = ‘./input_dir/images’
inp_msk_dir = ‘./input_dir/masks’
out_dir = ‘./output_dir’
height = 512
width = 512
start_num = 1

让我们用原始图像和蒙版组成一个文件列表,并对它们进行拆分:

input_images_list = glob.glob(inp_img_dir + ‘/*.jpg’)
input_masks_list = glob.glob(inp_msk_dir + ‘/*.png’)
split(inp_img_dir, inp_msk_dir, out_dir, height, width, start_num)

例如,使用以下代码显示了两个原始图像和遮罩:

for i, (image_path, mask_path) in enumerate(zip(input_images_list,
                                                input_masks_list)):
    fig, [ax1, ax2] = plt.subplots(1, 2, figsize=(18, 9))
    image = mpimg.imread(image_path)
    mask = mpimg.imread(mask_path)
    ax1.set_title(‘Image ‘ + str(i+1))
    ax1.imshow(image)
    ax2.imshow(mask)
    ax2.set_title(‘Mask ‘ + str(i+1))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图像由 Oleksii Sheremet 使用 matplotlib 模块创建

使用以下功能,您可以显示分割图像的所有部分(分为 8 个部分):

def image_part_plotter(images_list, offset):
    fig = plt.figure(figsize=(12, 6))
    columns = 4
    rows = 2
    # ax enables access to manipulate each of subplots
    ax = []
    for i in range(columns*rows):
        # create subplot and append to ax
        img = mpimg.imread(images_list[i+offset])
        ax.append(fig.add_subplot(rows, columns, i+1))
        ax[-1].set_title(“image part number “ + str(i+1))
        plt.imshow(img)
    plt.show() # Render the plot

让我们看看我们得到了什么作为图像和面具分裂的结果。对于第一幅图像:

image_part_plotter(output_images_list, 0)
image_part_plotter(output_masks_list, 0)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图像由 Oleksii Sheremet 使用 matplotlib 模块创建

image_part_plotter(output_images_list, 8)
image_part_plotter(output_masks_list, 8)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图像由 Oleksii Sheremet 使用 matplotlib 模块创建

结论

使用所提出的方法分割的图像和掩模以相同的文件名保存在不同的目录中,即,如果文件*’。/output _ dir/images/1 _ 00001 . png '在有图像的文件夹中,然后是文件。/output _ dir/masks/1 _ 00001 . png '*会在带有掩码的目录中对应它。分割图像和遮罩后,您可以对其每个部分应用增强(例如,更改亮度、对比度、旋转或翻转)。为此,只需添加增强功能。

参考文献

枕头(PIL 叉)

计算机视觉标注工具(CVAT)

本笔记本提供从外部来源加载和保存数据的方法

想象一个结合了深度学习能力和统计可解释性的单一模型

原文:https://towardsdatascience.com/imagine-a-single-model-combining-the-power-of-deep-learning-and-the-interpretability-of-statistics-d4f0c964b0d1?source=collection_archive---------40-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Unsplash 上由duanghorn Wiriya拍摄的照片

回归或分类问题通常用两种模型中的一种来分析:简单的统计模型或机器学习。尽管相对简单,但前者具有明显的可解释性优势(如所用变量的重要性)。相比之下,后者往往更强大,但由于其不透明性,通常被称为“黑盒模型”。

任何给定模型的性能都与其模块化程度直接相关。模块化程度越高,通常意味着整体精度越高(暂且忽略过度拟合)。然而,模块性越高也意味着我们越不知道一个给定的变量是如何解释目标的。换句话说,性能和可解释性似乎与它们的本质是对立的。但是如果事实并非总是如此呢?

在这篇文章中,我将首先从头构建一个强大的深度学习模型,其次,以一种允许我们解释某些解释变量是否可以说对目标变量产生了显著(积极或消极)影响的方式来调整它。在本文的其余部分,这个模型将被称为“SDL 模型”(用于重要的深度学习)。将使用前馈信息和反向传播误差(通过梯度下降)等概念,如果你还不熟悉这些概念,解释神经网络和深度学习的文章可能会帮助你理解文章。

加载用于训练 SDL 模型的数据

该模型将使用一些公开可用的数据进行训练。选择一个分类问题,IBM 股票(公开信息)的月对数收益的符号被选为目标变量。Fama & French 五因素将被用作解释变量。这些变量是 Rm-rf(市场相对于无风险利率的收益率差)、SMB(最大和最小公司之间的业绩差异)、HML(绝对股票最高和最低公司之间的业绩差异)、RMW(最赚钱和最不赚钱公司之间的业绩差异)和 CMA(保守投资公司和激进投资公司之间的业绩差异)。这些不同的数据集可以在我的 Github 上找到。首先导入包 Pandas 和 Numpy,然后运行以下代码以正确的格式加载所有数据。

用于加载数据的 Python 代码

理解 SDL 模型的大致结构

现在让我们仔细看看 SDL 模型的逻辑结构。一个好的起点是将其视为各种人工神经网络的组合,或者视为某些权重被约束为零的单个人工神经网络。为了说明一些可能的自相关性,我们对上述每个变量使用 t 时刻的回归值及其四个第一滞后值。然后,具有一个隐藏层的第一个人工神经网络可以应用于与同一变量相关的每组五个输入(在下图中用蓝色、橙色和黄色表示)。优化后(见下文),每个系统都给出一维输出。然后,五个获得的输出的系列可以用作没有隐藏层(即简单的逻辑回归)的最后一个人工神经网络(用绿色表示)的输入层,并且其 y 标签等于 1 或 0,这取决于 IBM 股票回报的符号。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

逻辑结构的示意图(I =中小企业、HML、RMW 和 j=1,2,3)

然而,仅仅通过组合这些不同的子模型来构建最终模型是不可能的。开始时,与五个神经元的最佳值相关的信息,即前五个 ANN 的各自输出,是未知的。因此,不可能调整权重来最大程度地降低成本函数,因为该函数本身是使用输出层的实际值和这些未知最优值之间的差来计算的。为了克服这个问题,我们将建立 SDL 模型作为一个单一的监督模型,具有五乘五个特征(Fama 和 French 五个因子的滞后值)和一个输出(IBM 股票回报的符号)。与此同时,必须对模型的大多数权重添加一些约束,以符合上述逻辑。在下图中,虚线表示约束为零的权重。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

模型权重的图示-显示了约束和非约束

用 Python 实现 SDL 模型

步骤 1:初始化

现在让我们转到 Python 实现。在初始化下面介绍的 NeuralNetwork 类之前,已经执行了一些必要的步骤(训练测试分割和一些数据预处理,以确保数据格式是正确的)。也可以在我的 Github 上查看这段代码。我们用四个不同的特征初始化一个新的模型。x 和 y 分别表示输入训练矩阵和目标训练向量。Lamb1 是正则化参数,类似于线性回归中的 Ridge,learningr 是模型的学习速率(反向传播误差时校正权重的力度)。然后用-15 和 15 之间的一些随机数初始化所有非约束权重。这个宽范围用于引入显著的可变性。这里值得一提的最后一点是,输出向量(用零值初始化)旨在包含在整个模型中“前馈”输入后获得的结果。误差向量将被构建为该向量和 y 向量之间的差。

用于模型类初始化的 Python 代码

第二步:前馈

推理的下一步包括通过各层前馈输入。首先,输入矩阵(大小为 n * 25-n 是数据集的长度)乘以第一个权重矩阵(大小为 25*10)。每个第一隐藏层的神经元值最终等于 sigmoid 函数的输出,以矩阵乘法的相关边际结果作为变量。使用相同的方法来处理下面的层。一切都用数学方法总结如下。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

前馈过程背后的数学。

在 Python 中,我们的 NeuralNetwork 类中的前馈方法可以通过以下方式实现。

前馈的 Python 代码

步骤 3:错误反向传播

一旦获得了输出层,就可以计算成本函数。这用于衡量预测输出与实际目标的差距。推理的下一步在于计算该成本函数相对于不同权重的导数(从权重 3 开始,然后是权重 2,最后是权重 1)。这旨在理解成本函数的哪个部分与哪个权重相关联。然后有可能以最小化成本函数的方式更新权重(根据所选择的学习速率,只有一部分导数被减去到当前权重)。下面总结了最初的数学步骤——计算基于链式法则原理和符号”。*”用于表示逐元素的矩阵乘法。注意,从第二个隐藏层开始,我们再次从误差向量的边缘元素开始推理。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

误差反向传播第一步背后的数学

最相关的代码行如下所示。请再次注意,许多不太重要的行在这里没有显示,但是可以在 my Github 上找到。

反向传播的 Python 代码-仅最相关

步骤 4:优化和选择λ和学习率参数的最佳值

推理的最后一步包括重复步骤 2 和步骤 3(即,具有不断发展的权重和反向传播误差的前馈信息)。当成本函数不再降低时,该过程最终停止。我们使用简化的交叉验证来选择 lambda 和学习率参数的最佳值(即,针对测试的所有 lambda 学习率对,计算给定测试集的分类准确度,然后保留模型表现最佳的对)。在前面介绍的金融数据上,使用等于(0.15,0.3)的元组(lambda,学习率)可以获得测试集上的最佳分类精度(大约 70% —可以添加一些 IBM 特质变量来增加这个数字)。

“交叉验证”选择最佳参数值

步骤 5:变量的重要性

现在证明,SDL 模式运行良好。在大多数情况下,它能够根据市场相关变量的当前和过去的值,正确地对 IBM 收益的符号进行分类。工作完成了一半!

下面的方法将解释所选择的变量如何帮助解释 IBM 收益为正的概率。你可能已经注意到,我们的 SDL 本质上是两种模式的结合。第一种是五个神经网络与一个隐藏层的组合。优化 SDL 模型的方式确保了这些子模型中的每一个的最终神经元处的值是相同外生变量的五个时间输入的最优变换的结果(显然可能不是每个单个数据行的情况,而它在考虑所有数据时检查出来)。然后,这些经过优化转换的变量被用作第二个模型组件(最后一个没有隐藏层的神经网络,基本上是逻辑回归)的输入。从第二个模型中可以得出一定的意义。—对于每个外部变量,通过将相关子模型的最后一个神经元值(向量)乘以应用于该最后一个神经元的权重(标量)获得的向量平均值将用于该目的。这给出了插入 sigmoid 函数的平均绝对数字的概念,以最终估计 IBM 股票收益为正的概率。这一估计应该是准确的,而不仅仅是 SDL 模型幸运收敛的结果。因此导出了该估计量的非参数分布。该分布建立在运行相同代码 100 次所获得的一组值的基础上。如果这个分布的 2.5%和 97.5%的分位数要么都是正的,要么都是负的,那么就可以断定这个外生变量是显著的(α=5%),分别是正的或负的!

如下图所示,变量(Mkt-rf)与 IBM 收益的符号正相关。换句话说,市场价差越大,IBM 的回报率越有可能为正,这似乎是合乎逻辑的。类似地,CMA 变量似乎对 IBM 收益为正数的概率产生了负面影响。换句话说,保守投资公司和激进投资公司之间的业绩差异越大,IBM 取得正回报的可能性就越低。由于长的右尾,这种关系是显著的,但仅在任何置信水平 1-α-α> 1%时。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这一部分的代码可以在下面找到。

Python 代码推导出一些变量的意义

模型的结论和已知限制

总之,在运行 SDL 模型的 Python 实现时获得的结果表明,性能和可解释性在一定程度上是可以结合的。绩效与适当的 IBM 股票回报分类相关联,可解释性与所使用的外生变量的正或负显著性相关联。

然而,这种方法并不完美。例如,同一个模型必须运行多次才能获得最终估计值的分布,这一事实耗费时间和 CPU。从方法学的角度来看,选择最佳参数值的交叉验证只在一个样本上进行。最后,可以认为,在输入可以取正值和负值的情况下,上一步中得出的重要性可能不再准确,但这可以通过对输入值进行适当的初始标准化来避免。

这只是我对这种创新的意义重大的深度学习模型研究的起点。我期待着关于如何使这项研究更上一层楼的反馈和想法,我很乐意讨论你可能有的任何想法,关于本文中解释的模型或其他可以调和性能和可解释性的逻辑结构。

想象一下,你的“数据”文件夹里没有…混乱!

原文:https://towardsdatascience.com/imagine-theres-no-mess-in-your-data-folder-859135bd1262?source=collection_archive---------61-----------------------

如果你尝试,它是容易的。想办法改善你与数据集的互动。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有时很难在你自己的数据中导航。艾萨克·奎萨达在 Unsplash 上的照片

首先我将介绍狐猴先生,他将伴随我们的思考过程。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

狐猴先生已经准备好冒险了!杜安·斯美塔纳Unsplash 拍摄的照片

我们走吧!

假设你和你的团队成员一直在做一个名字很酷的项目**“客户流失探测器 X”**。剩下的就是用一个合适的数据集来拟合我们同样酷的模型,然后部署它。

你看着“数据”目录,它立刻让你充满困惑。

你的项目某处:
data/
├──user _ activity _ April _ 2020 . CSV
├──user _ activity _ may _ 2020 . CSV
├──user _ activity _ April _ 2020 _ cleaned _ df _ v1 . CSV
├──user _ activity _ may _ 2020 _ broken . CSV
├──user _ activity _ may _ 2020 _ v2 . CSV
├──user _ activity _ may _ 2020

看着眼熟?我知道那种感觉,兄弟。

想象一下这样一个美好的世界,在那里再也不会出现如此混乱的局面。即使你只对四月份的数据集感兴趣,在过滤掉其他数据后,你会得到:

data/
├──user _ activity _ April _ 2020 . CSV
├──user _ activity _ April _ 2020 _ cleaned _ df _ v1 . CSV
├──user _ activity _ April _ 2020 _ cleaned _ df _ the _ best . CSV
├──user _ activity _ April _ 2020 _ cleaned _ df . CSV
└──user _ activity _ April _ 2020 _ cleaned _ df _ improved . CSV

现在清楚该选哪一个了吗?嘿,狐猴先生,你说呢?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

别担心,狐猴先生,我们会解决的!Amy Reed 在 Unsplash 上拍摄的照片

混乱的根源。

嗯,通常我们在做令人兴奋的事情时总是很匆忙。有一天,你向自己承诺,记住哪个数据集是哪个数据集是很容易的。尽管如此,时间飞逝,你知道!截止日期已经悄悄逼近你了。

绝对必要的是,必须使用正确的生产数据。垃圾进——垃圾出,记得吗?你现在做什么?

那么…哪个数据集是正确的呢?

首先,你检查所有的笔记本,比较指标或其他计算,你花一些时间,然后再多一点…咻!你几乎 100%确定那个user _ activity _ April _ 2020 _ cleaned _ df _ improved . CSV数据集就是你要找的那个。

没那么难。哦,等一下…

您刚刚想起需要使用最新的可用数据重新生成数据集。唯一的障碍是找到你使用的代码。谢天谢地,你一直在使用 git 并且只花了大约一个小时就找到了根并测试了一切。是的,我是在讽刺。最坏的情况——您在 git 历史中没有任何相关内容。

有哪些不同的做法?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

狐猴先生也在寻找答案。布兰登·泰特Unsplash 上拍摄的照片

我已经介绍了两个问题:

  • 很难理解不同的变换数据集实际上代表了什么
  • 毕竟很难跟踪这些数据集是如何生成的

作为奖励:如何使从任何文件或笔记本中读取数据集变得容易?

有一种简单的方法可以解决第一个问题,那就是提供一个详细的文件名。

第二个要棘手得多。显然,负责转换的代码总是分离的,数据本身无法告诉我们在哪里可以找到它。

我们将在本文的剩余部分尝试找到所有这些问题的解决方案。

做一个数据集的小梦。

你可能会说我是一个梦想家,但让我们想出摆脱这种状态的选择:

呀,看起来真恶心…太不可移植了,太容易出错了。但是:我们可以做得更好!

我呼吁大家集思广益!现在重要的是接口,而不是实现。

我不想直接处理文件路径。

我们通过隐藏所有获取数据集的逻辑来指定我们正在处理的项目和文件名。感觉好多了,虽然我仍然需要知道确切的文件名。不太方便。

去掉文件名。

文件名暗示数据集与user _ activity _ April _ 2020 . CSV数据集相关。的确,user _ activity _ April _ 2020 _ cleaned _ df _ improved . CSV只是它的一个改造版本。在签名中把它们分开是个好主意。

我不想关心文件格式!

很公平。

这么一件小事,却造成了如此大的差别!现在,我可以左右阅读数据集,一切都会正常工作。

普通函数不是一个可伸缩的解决方案。我需要一张“脸”来代表它!我们需要一些神奇的东西…

最后,我们来到了这里:

在我的想象中,勇敢的魔术师来拯救我们的时间和理智了!看起来像魔术,真的。在项目中,我不想处理存储数据集的绝对或相对路径,我不关心使用哪种格式保存它。我只是需要它留在记忆里。我现在就需要!从存储库中的任何位置。当在同一个存储库中与许多团队成员一起工作时,这是特别需要的。注意转换 id 参数的值。是**“model _ ready”,比“cleaned _ df _ improved”**更直观。

不可避免的时刻已经到来。是时候回到现实,考虑一个可能的实现了。

它怎么知道从哪里获取数据?

如果我是 MagicDfReader ,我更希望有一些描述数据和相关转换的配置文件。配置是伟大的,他们可以记住任何事情,让我们有时间做更重要的事情。

它能包含什么有用的信息呢?稍加思考后,我可以勾勒出以下几点:

df_id 这里只是提醒一下配置属于哪个数据集。然后我们可以在元数据部分放置任何东西。知道谁创建了配置以及何时收集了数据是非常有价值的。 initial_df_format 信息将被 MagicDfReader 用来知道如何读取它。

我们谈了很多转变,不是吗?它们也必须在配置中找到。我一般能想到两种类型的转换:

  • 内存中的——每当我们想要访问数据时,它们就会运行
  • 永久 —它们运行一次,对磁盘进行以下序列化

例如,我们可能希望在每次读取数据集时将日期列转换为日期时间类型,但是也有一些列我们希望永久删除。它在配置中会是什么样子?

你觉得怎么样?看起来不言自明。

我们可以通过添加注释来澄清所有字段,使其更加详细:

如果在某个时间点,您想知道数据集是如何生成的——只需查看相关的配置文件。你想让它重生?没问题,只需删除旧文件并让 MagicDfReader 为您获取即可。它将遵循您在配置中提供的配方。如果你的同事负责一些转变,你甚至不需要知道它是如何完成的。 MagicDfReader 送来,宝贝。然而,仍有差距需要填补。比如具体有哪些动作? to_date 和 **drop_cols,**在哪里实现?

是的,我承认…是时候进行无耻而谦逊的自我宣传了!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我就像这里的狐猴先生一样谦逊。照片由乌列尔·索伯兰斯Unsplash 上拍摄

一旦我的想象力最终引导我找到了键盘,我就做了一个几乎按照我描述的方式工作的库。我准备了一个相当详细的 Jupyter 笔记本,里面有它的内部细节,所以我不想在这里用很多代码打扰你。

这个库叫做 df-and-order 。就像法律&命令一样。你知道,我喜欢各种形式的有序,我的“数据”文件夹中的有序是必须的,因为我有这样一个库。

让我向您展示这个库的主要组件以及真正的配置是什么样子的。

DfReader

真正的 DfReader 也很不起眼,名字里没有任何与魔法相关的东西。

创建 **DfReader 的实例需要两个参数。如你所见,它对你的项目一无所知,它期望得到一个【数据】**的文件夹路径。但是不要担心,没有什么比创建自己的 DfReader 子类更容易的了,它可以动态地生成 dir_path 。这么几行代码和你得到的 MagicDfReader 我们前面讲过的! format_to_cache_map 参数引出另一个类。

DfCache

应该被子类化,包含一个如何读取和保存特定格式的数据帧的逻辑。只要看一看示例子类,一切就都清楚了!

是的,它最终成为了熊猫的内置方法的简单包装。下面是一个格式 _ 到 _ 缓存 _ 映射参数值的例子:

现在 DfReader 知道如何处理这些格式。

lib 的真实配置如何?

看起来几乎和以前一样! module_path 是对具有负责转换的代码的文件的引用。您编写一些代码,然后将所有需要的参数暴露给配置文件,一切都变得清晰和可重复。查看上述深度笔记本了解详情

lib 是用熊猫写的。DataFrame 记住了,但是如果需要的话,它可以很容易地成为与框架无关的工具。也可以对其进行修改,以处理非本地文件。 DfCache 子类可以访问一些外部资源等。

lib 正处于发展的早期阶段,所以旅程才刚刚开始。

重要提示:

df-and-order是关于组织你的数据文件并使用基本转换简化对它们的访问,而不是一个真正的数据管道框架。

良好做法:

  • 您有一个庞大的原始数据框架,并且希望保留它的预处理版本,以便能够快速适应模型。您使用 df-and-order 来描述所有需要的转换。
  • 您希望在后台将所有日期列从 str 转换为 datetime 类型。
  • 您希望对类型进行优化以满足数据需求(比如对小范围数据使用 8 位整数而不是 64 位整数)。类型优化可以作为单独的转换来实现。
  • 您希望为同一个数据集计算不同的目标。例如,您想从二元分类切换到多分类。

不良做法:

  • 你使用 df 和 order 进行缩放、虚拟编码等操作。没人能阻止你这么做,但是这样的操作有更好的选择。
  • 您在转换中编写一些复杂的逻辑,如发出请求、获取和推送数据等。
  • 您在转换中安排了一些外部依赖项。所有的参数都应该放在配置文件中,以保持可再现性。

结论

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

该冷静了,狐猴先生!拉明·尼乌文休斯在 Unsplash 上的照片

即使你不愿意尝试我试图驯服混乱的结果,也许这篇文章能帮助你正确看待事情。再现性在数据业务中非常重要,所以不要忽视这个方面,否则就太晚了。

我希望有一天你会加入回购!随时留下评论,开放的问题等!我很乐意与你交流。

注意安全,祝你好运!

想象一个没有变形金刚的世界——单头关注 RNN

原文:https://towardsdatascience.com/imagining-a-world-without-transformers-single-headed-attention-rnn-844cca2580f9?source=collection_archive---------18-----------------------

从一篇最有趣的 NLP 论文中提取关键思想,描绘一个没有伯特模型家族的世界

TL;速度三角形定位法(dead reckoning)

2019 年是变革之年——在不同领域完成了大量工作(超过 5000 次引用),并解决了扩展和应用 BERT 的 NLP 问题。2019 年 11 月发表的一篇论文带回了不久前 RNNs 统治几乎所有 NLP 任务的旧记忆。这篇博文总结了《单头注意力 RNN:停止用你的头脑思考》一文的主要观点,作者是 T2。作者分享了一些非常有趣的想法——这篇论文以讽刺的方式写成,通篇引用了许多微妙的内容,读起来很有趣。另一方面,对于一些人来说,持续地跟随和吸收变得有点困难(我读了几遍以完全理解)。我将尽力总结论文传达的要点。我还会试着为那些可能不太了解必要背景的读者设置一些背景,以使这篇文章对所有人都有用。以下是我们将深入探讨的要点:

  1. 背景:赫特奖和理解为什么语言建模在 NLP 领域仍然是一个有趣的任务。
  2. **模型架构:**仔细观察具有基于指针的注意机制和某个“boom”前馈层的 SHA-RNN 模型架构,两者都伴随着层规范化。
  3. **标记化攻击&教师强制:**变化的标记化方案如何影响模型训练和评估行为。
  4. 资源节约:构建可以在单个 GPU 机器上实际训练的模型,并且不严重依赖大量的超参数调优。
  5. **想象一个没有变形金刚的世界:**单向研究追求的后果,以及为什么采取反向立场可能是推动研究和工程领域整体发展的关键。

背景

语言建模是在给定之前出现过的单词的情况下,预测序列中的下一个单词的任务。包括机器翻译、语音识别等许多自然语言处理任务的核心都是语言模型。作者有趣地引用了通用近似定理,该定理指出,一个神经网络,当配备了足够的参数时,能够处理手头任何任务的所有更精细的复杂性。从理论上讲,语言模型仅仅是人类语言书写方式的反映,本身没有任何重要的原始智能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

赫特奖鼓励压缩自然语言文本的任务,以尽可能最有效的方式学习和再现文本序列,具体来说,就是来自维基百科的 100 MB 文本文件(enwik8)可以压缩多少。在本文中,作者演示了一个简单的基于 LSTM 的模型(经过一些修改),具有单个注意力头,与许多高级的基于 transformer 的模型相比,尽管内存和资源消耗较低,但性能非常接近。

模型架构

作者将沙-RNN 模型的架构描述为梅里蒂等人(2018a)介绍的 AWD-LSTM 模型的升级版。值得一提的是,快速回顾一下 AWD-LSTM 模型,以便更好地理解沙-RNN 模型可能是个好主意。ASGD 权重下降 LSTM 模型对 lstm 应用了几种正则化技术,使其成为强大的语言建模标准,但这里有两个最突出的:

  1. drop connect:drop connect 是一种正则化技术,由 Yann LeCunn 在 NYU 的团队于 2013 年首次推出,基于辍学正则化策略的思想。在 DropConnect 设置中,随机选择的权重子集为零,这与 dropout 相反,dropout 在给定的训练迭代中随机关闭一些隐藏单元激活。请看下图,它使这一解释更加直观:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

丢弃和丢弃连接正则化技术的比较

  1. NT-ASGD :顾名思义,非单调触发平均随机梯度下降在两个意义上是传统 SGD 的变体。首先,它通过将来自先前迭代的权重与反向传递期间返回的当前训练步长权重进行平均来考虑这些权重。第二,只有当模型的主要评估度量在一定的训练迭代周期内没有改善时,才执行这种平均。

在此背景下,我们可以看看沙-RNN 模型架构的一些主要组件:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如图所示, 每个 SHA-RNN 层只包含一个注意力头,通过消除更新和维护多个矩阵 的需要,帮助保持模型的内存消耗最小。另一方面,多头注意力需要融合每个头的计算,以产生变压器层的最终输出。SHA-RNN 还主要利用文本中的顺序性,而不是变压器,变压器仅通过时间和位置编码信号微妙地跟踪序列的概念,这可能会引入更多的参数供模型跟踪。

SHA-RNN 图层在多个点加载了图层归一化步骤,以在每个要素维度上对要素进行归一化,这在之前已被证明可减少训练时间并提高稳定性。有一个被称为“boom”层的前馈层,它基本上使用 GeLU(高斯误差线性单位)激活来创建最终输出向量。尽管 AWD-LSTM 使用了 NT-ASGD 优化器,但作者报告的结果与之前使用 LAMB 优化器(用于批量训练的分层自适应矩优化器)的实验一致,该优化器提高了较大批量的收敛性。在这种情况下,深入 LAMB 优化器的细节可能会很棘手,但我喜欢这篇博文,如果你有兴趣了解更多,这篇博文很好地解释了它。

标记化攻击和教师强迫

作者指出,不同的标记化方案在我们如何训练、评估和比较不同的语言模型中起着重要作用。特别是,比较单词和子单词级别模型之间的困惑分数可能不是很简单。单词块标记化器通常将单词分割成更小的复合子词,这样可以得到更紧凑的词汇表和更好的模型参数利用率——这很好。此外,在训练过程中,目标令牌作为下一个输入(教师强制)被传递到该层,使得该模型在单词的初始部分严重影响给定单词的后续部分的情况下获得轻微优势。在实践中说明这一点的一个很好的例子是,当模型必须预测“邓布利多”时,从单词 pieces**【D】**【umble】【dore】中的第一个标记“D”可以获得大量信息,而单词标记化模型只能预测一次。如果你想知道这些单词块标记化算法是如何工作的,我的上一篇博客文章是关于将字节对编码重新用于子单词标记化。

资源节约

在过去的几年里,我们在深度学习领域取得了巨大的突破,这主要归功于大规模计算资源(GPU/TPU 集群)的可用性以及我们高效利用这些资源的能力(分布式机器学习)。虽然大多数大型组织都有无限的计算能力,但独立研究人员很难重现结果。例如,对 BERT 进行预训练需要 4 天时间,16 个 Google cloud TPUs 很容易就花费了几万美元——不确定你的,但那肯定会在我的口袋里烧一个大洞。

“无论如何,我所有最好的作品似乎都来自相对较少的资源和创造性.”

值得称赞的是,作者能够在不到 24 小时的时间内,在单个 GPU 机器上训练沙-RNN 模型,并且没有进行大量的超参数调优。

想象一个没有变形金刚的世界

“为什么要像飞蛾扑向灯泡一样,只向一个方向推进呢?”

自从引入 transformer 层以来,研究界在去年取得了惊人的进步。作者在沙-RNN 论文中所做的许多工作也受到了这项工作和过去许多聪明的工作的启发。但是,作者提出了在研究人员的工具包中具有多样性和竞争性的模型架构的重要性,以便能够为手头的给定任务选择合适的模型,而不是仅仅依赖于一种类型的模型。这也需要更好的工具和效率的提高,而不仅仅是选择几个架构,而是共同推进研究流的所有方面。但是最后,很难说会发生什么,但是永远不要忘记你从哪里来,因为有一天你可能不得不回去!

参考

  1. 梅里蒂,S. (2019)。单头注意力 RNN:停止用你的头脑思考。 arXiv 预印本 arXiv:1911.11423
  2. 梅里蒂,s .,凯斯卡尔,N. S .,&索彻,R. (2017)。规范和优化 LSTM 语言模型。 arXiv 预印本 arXiv:1708.02182
  3. 万,李,,米,张,s,乐存,y,&弗格斯,R. (2013 年 2 月)。使用 dropconnect 正则化神经网络。在机器学习国际会议(第 1058–1066 页)。
  4. Vaswani,a .、Shazeer,n .、Parmar,n .、Uszkoreit,j .、Jones,l .、Gomez,A. N .、… & Polosukhin,I. (2017)。你需要的只是关注。在神经信息处理系统的进展(第 5998–6008 页)。
  5. Smerity/sha-rnn 代码库—https://github.com/Smerity/sha-rnn
  6. TWIML AI 播客—https://soundcloud.com/twiml/single-headed-attention-rnn

根据类和物体想象世界

原文:https://towardsdatascience.com/imagining-the-world-in-terms-of-classes-and-objects-fe04833a788c?source=collection_archive---------39-----------------------

面向对象编程的直觉

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

凯利·西克玛在 Unsplash 上的照片

世界一片混乱!为了理解它,人类倾向于对事物进行组织、分类和结构化。分类帮助我们将复杂的事物分解成更小的部分。它塑造了我们的思维,给了我们方向。让我们想想世界上的“一切”。理解这个想法非常复杂。但是我们可以将它分成如下几个样本类别:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

分类给了我们一些控制来更好地管理复杂性。它使我们能够识别、区分和理解。属于每个类的事物或 【对象】 可以共享共同的属性或 【属性】 并且可以以共同的方式表现。我们可以说,属于某个特定类的对象可能以类似的方式 【功能】 。比方说,我们把“动物”作为一门课。我们可以想象大象、兔子、奶牛、猴子等属于这一类,这些动物执行一些共同的功能,如吃、睡、跑等。事实上,就类和函数而言,你可以想象世界上几乎任何概念。让我们看看下面的句子

《罗汉正在访问纽约》

识别句子中的名词——Rohan 和 New York。你可以把“罗汉”想象成一个属于“游客”类的物体。类似地,“纽约”是属于类别“旅游目的地”的对象。

现在识别句子中的 动词 。“拜访”是罗汉的一个动作。所以,你可以想象“拜访”是“罗汉”的功能。

背后的直觉是——当你在为旅游行业编写软件时,你可以用“类”(游客和旅游目的地)的形式来构造你的代码。“参观”是“游客”类的一个功能(所有游客都会参观某个地方)。“Rohan”是“Tourist”类的一个 实例 ,而“New York”是“Tourist Destination”类的一个实例。这些被称为“对象”。每个游客和每个目的地都可以表示为这些通用类的对象。另外,请注意,每个对象都有共同的属性。在我们的示例中,来自旅游类的对象可以具有像姓名、年龄、地址这样的属性,而来自旅游目的地类的对象可以具有像位置地址这样的属性。

类和对象的区别在于——类是定义或模板,而对象是定义的实例。

课堂是一个食谱。该物体是由该食谱制成的一道菜。

几乎每个现实世界的概念都可以用类、对象和函数来表达。事物是类,事物执行的动作是函数,事物的实际值是对象。

动物是一个类。猴子是一个物体。跳跃是功能。

车辆是一个类。奔驰是一个物体。加速度是函数。

Python 中的类和对象

让我们看看 Python 3 中是如何定义一个类的

# Class for animals
class Animal:

 category = “pets”

 def __init__(self, name, age):
 self.name = name
 self.age = age

 def printname(self):
     print(“Name of this animal is: “, self.name)

 def printage(self):
     print(“Age of this animal is: “, self.age)

 def move(self):
     print(“Running”)# Instantiate Animal objects
dog = Animal(“Titu”, 5)
cat = Animal(“Sarah”, 6)# Call Instance Methods
dog.printname()
dog.printage()
dog.move()cat.printname()
cat.printage()
cat.move()

输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们来解剖一下:

  1. **类的声明:我们使用“Class”**关键字定义了一个名为“Animal”的类。
class Animal:

**2。对象:**类将通过它的“对象”来实现。这些被称为这个类的“实例”。

dog = Animal(“Titu”, 5)
cat = Animal(“Sarah”, 6)

**3。实例属性:**一个类的对象有一定的属性。在我们的例子中,动物有年龄和名字。**__init__()**方法用于通过分配默认值(或状态)来初始化一个对象的属性。这个方法至少有一个参数和“self”。

def __init__(self, name, age):
 self.name = name
 self.age = age

“自我”意味着属性是对象本身的一部分。变量“name”和“age”只属于这个对象,独立于程序中的任何其他对象或通用变量。

***__init__()***方法不是专门调用的。一旦对象被声明,它就会被自动调用。

**4。类别属性:**可能有一些类别共有的属性,即该类别的所有对象。在我们的例子中,category 就是这样一个属性

category = “pets”

所以在这个例子中,所有的对象(猫和狗)都是“宠物”。

**5。实例方法:**这些函数定义对象的行为。像**__init__()**方法一样,实例方法的第一个参数也是 Self。在我们的例子中,“printname”、“printage”和 move 是实例方法

def printname(self):
     print(“Name of this animal is: “, self.name)

 def printage(self):
     print(“Age of this animal is: “, self.age)

 def move(self):
     print(“Running”)

关于 Python 数据类型的一句话

让我们用 Python 声明两个变量,看看它们的类型:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上面的输出显示‘a’属于一个名为‘int’的类。这也暗示‘a’是‘int’类的对象(实例)。同样,‘name’属于一个叫做‘str’的类。Name 实际上是这个 String 类的一个实例。

有趣的是,python 的内置数据类型实际上是类。这种数据类型的变量(如整数或字符串)实际上是该类的实例。实际上,Python 中的一切都是某个类的对象。 (是的……连函数)。您可以使用 help()函数来检查这些类的定义

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个关于 Python 内置数据类型的有趣事实给了我们一个关于类和对象真正用途的线索。

类用于创建新的用户定义的数据类型。

使用自己的数据类型增强了软件程序的可重用性和可维护性。

我们的世界由实体组成,这些实体相互作用。类和对象对现实世界的实体以及它们之间的关系进行建模。因此,围绕他们构建你的软件,增加了人性化的一面。这使得程序更容易阅读和理解。

乔布斯 曾被要求描述什么是面向对象软件?他的回答是:

物如其人。他们是有生命的,会呼吸的东西,体内有如何做事情的知识,体内有记忆,所以他们能记住事情。你不是在很低的层次上与他们互动,而是在很高的抽象层次上与他们互动,就像我们现在做的一样。举个例子:如果我是你的洗衣对象,你可以把你的脏衣服给我,然后给我发一条信息,说“你能帮我把衣服洗了吗?”我碰巧知道旧金山最好的洗衣店在哪里。我会说英语,口袋里也有钱。所以我出去叫了一辆出租车,告诉司机带我去旧金山的这个地方。我去洗你的衣服,跳上出租车,回到这里。我把你的干净衣服给你,并说:“这是你的干净衣服。”你不知道我是怎么做到的。你对洗衣店一无所知。也许你会说法语,但你甚至不会叫出租车。你不能为一个付钱,你口袋里没有美元。然而,我知道如何做到这一切。你不需要知道这些。所有的复杂性都隐藏在我的内心,我们能够在一个非常高的抽象层次上进行互动。物体就是这样。它们封装了复杂性,而这种复杂性的接口是高层次的。

分类中的不平衡数据:一般解决方案和案例研究

原文:https://towardsdatascience.com/imbalanced-data-in-classification-general-solution-case-study-169f2e18b017?source=collection_archive---------20-----------------------

在错误分类一个二进制类比另一个二进制类代价更高的情况下,找到最佳分类器和重采样技术来处理不平衡数据

作者:哈德尔·哈马德& 闵周 ,博士

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片启发:https://www . vector stock . com/royalty-free-vector/balance-scale-isolated-icon-design-vector-9656446

在处理分类问题时,如何处理一个数据集,该数据集的一个二进制类中的数据点比另一个二进制类中的数据点多得多?这样的数据集被称为不平衡。简单地在不平衡的数据上实现一个分类模型并期望最好的结果是明智的吗?有许多重采样技术可以“平衡”不平衡的数据集和大量的分类模型。我们如何为我们的问题选择一个最优的呢?

本文旨在为数据科学领域的非技术从业者[https://arxiv.org/abs/2002.04592]总结以下学术研究“不平衡分类:面向目标的综述”。这篇文章对于至少具备机器学习基础知识的读者来说是容易理解的。

一、简介

不平衡的数据集在所有行业中都非常普遍。假设您为一家银行工作,并且您有一份带有欺诈标签的信用卡交易数据。您发现欺诈类别非常不平衡(0.17%的数据是欺诈=0,99.83%的数据是非欺诈=1)。在这种不平衡的数据上天真地实现分类模型可能会导致非常低的预测准确性。在分类问题中,几乎不可能完美地同时预测两个类别(欺诈和非欺诈)。这是因为分类模型带有两种类型的错误,类型 I 和类型 II,并且本质上在这两者之间存在权衡。第一类错误表示将欺诈交易误归类为非欺诈交易的可能性。第二类错误的意思正好相反:将非欺诈交易误归类为欺诈的概率。通常情况下,第一类错误比第二类错误的代价更高。我们的案例就是一个例子,因为你可能会因为错误地将客户的交易标记为欺诈而激怒他们,从而有可能失去他们。然而,一般来说,根据问题的性质,您可以选择不同地对待类型 I 和类型 II 错误的权重,这相应地决定了操作的分类范例。

我们将简要概述分类范例和重采样技术。然后,我们将使用上面的信用卡欺诈数据的例子,这是一个真实的案例,将每种重采样技术与不同分类范例下的分类模型配对。目标是为每个范例找到重采样技术与分类模型的最佳组合。在本文的最后,我们提供了应用分类范例和重采样技术编写 R 代码的例子。

二。三种分类范式

每种分类模式对第一类和第二类错误的权重处理不同:

1.经典分类(CC)范式将总体分类误差降至最低,这意味着 I 类和 II 类误差的权重相等。在第一类错误可能比第二类错误更严重的情况下,或者相反的情况下,它不能很好地服务。因此,我们接下来将介绍另外两个解决不对称错误重要性问题的范例。

2.成本敏感(CS)学习范式为第一类和第二类错误分配不同的成本,然后最小化它们的总量。它有多种方法,但是我们将把后处理方法应用到我们的案例研究中。CS 学习的缺点是为 I 型和 II 型错误分配成本值,因为它们通常是未知的。另一个缺点是,即使我们将经验 I 型误差调整到等于预先指定的水平(α),真实的总体水平 I 型误差仍然有超过α的一些可能性。然而,尼曼-皮尔逊处理这个问题。

  1. Neyman-Pearson 范式是一种新兴的统计框架,通过旨在将第二类误差最小化,同时将第一类误差控制在理想水平之下,来控制不对称误差。要了解更多,请阅读以下论文:尼曼-皮尔逊分类算法和 NP 接收机操作特性

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 1:每个分类范式的学习目标

三。重采样技术

我们利用重采样技术来减轻不平衡的类大小对分类模型预测能力的影响。重采样技术通过平衡少数类和多数类中的数据点数量来创建新的训练数据集。我们将讨论三种不同的技术:欠采样、过采样和混合技术。

1.欠采样方法使用两种通用方法消除多数类中数据点的子集。第一个是*随机欠采样,*随机丢弃多数类的数据点,以平衡其大小与少数类的大小。虽然这是一种简单省时的方法,但它可能会产生数据偏差,因为它会抛出一些信息,使数据样本不太能代表真实的总体。第二种技术,*基于聚类的欠采样,*可以减弱这种偏差问题。它对多数类应用聚类算法,以便获得与少数类的大小相平衡的几个聚类。如果多数类的规模很大,这种技术可能会很慢。欠采样的一个普遍缺点是,如果大多数类的大部分数据被丢弃,它可能会导致关键信息丢失。

2.过采样增加少数类中数据点的数量,以平衡多数类的大小。随机过采样通过随机复制少数类中的数据点来实现这一点,直到它们与多数类的大小成同等比例。合成少数过采样技术 (SMOTE)利用 k 最近邻为少数类生成新的数据点,这些数据点与多数类的大小成正比。过采样方法可能导致过拟合,并且相对于欠采样,它通常需要更长的训练时间。

3.混合技术仅仅是欠采样和过采样技术的结合。它同时应用过采样来增加少数类中数据点的数量,同时应用欠采样来减少多数类中数据点的数量。

四。真实案例分析:信用卡欺诈数据

数据集描述

  • *数据集来源:*卡格尔【https://www.kaggle.com/mlg-ulb/creditcardfraud】T2
  • 预测值个数: 30
  • *记录/交易笔数:*284807 笔
  • 响应变量:“Class”,在欺诈的情况下取值 1,否则取值 0。在我们的数据处理中,我们在研究中颠倒了标签,所以如果欺诈,0 类;否则 1。
  • *不平衡率:*0.17%(284,807,492 ÷ 284807 中的 492 笔欺诈交易)

数据处理

由于我们的计算能力有限,我们从上述大型数据集中提取了一个子样本。我们指定不平衡比(IR)为 100;即 IR=100。我们为类别 0(欺诈)随机选择 n0=300 个数据点,为类别 1 选择 n1=n0IR=30,000。这创建了我们的训练集。测试集由剩余的 0 级 m0=192,[492–300]和 1 级 m1=m0IR=19,200 组成。这种分割机制保证训练集和测试集的 IR 相等。

下面是我们使用的重采样技术

  • 无重采样:使用训练集,不对原始数据进行任何修改(在图表中,我们称之为“原始数据”)
  • 随机欠采样(我们称之为“欠采样”)
  • 过采样(“SMOTE”):我们使用 R 包 smotefamliy,v1.3.1,Siriseriwan 2019,默认选择最近邻
  • 混合:结合随机欠采样和 SMOTE

以下是我们应用的分类模型,后面是 R 包(注意:我们使用包的默认参数):

  • 逻辑回归(以 R 为基数的 glm 函数)
  • 支持向量机(R 包 e1071,v1.7.2,Meyer 等人 2019)
  • XGBoost (R 包 XGBoost,v0.90.0.2,陈等 2019)

对于分类范例,我们指定以下参数:

  • CS 学习范式:我们指定成本 C0=IR=100,C1 = 1;阈值=C0/(C0+C1)=100/101
  • NP 范式:我们指定α = 0.05,违反率δ = 0.05

表示|S|为集合 S 的基数,设 O = {CC,CS,NP},T = {Original,Under,SMOTE,Hybrid},C = {LR,SVM,XGB}。因此,它需要|O=3| × |T=4| × |C=3| = 36 个元素,如下面的图 1 所示,我们将在后面进行研究。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1:在我们的案例研究中检查了上述所有要素

五、评价指标

在评估我们的结果之前,我们需要首先通过回顾几个用于评估模型性能的评估指标来奠定基础。请注意,我们将少数类(欺诈)标记为 0,多数类(无欺诈)标记为 1。我们称 0 类(负面类,欺诈)和 1 类(正面类,欺诈)。

分类模型通常总结在一个叫做混淆矩阵的表格中,如下图所示。它被称为“混淆”,因为分类模型在从负面类别中识别正面类别时从来都不是完美的(也就是说,它们混淆了它们)。右边的对角线代表被错误地预测的标签,而左边的对角线代表被正确地预测的标签。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 2:混淆矩阵来源于 CS 范式下对原始数据的逻辑回归

混淆矩阵包括以下内容:

  • 真阴性(TN):正确预测为阴性(欺诈)的数据点数
  • 假阴性(FN):错误预测为阴性的数据点数
  • 真阳性(TP): 正确预测为阳性(无欺诈)的数据点数
  • 假阳性(FP):错误地预测为阳性的数据点数

***—第一类错误:*将欺诈交易误归类为非欺诈交易的比例:
= FP/(TN+FP)
= 22/(170+22)= 0.1146

***—第二类错误:*将非欺诈交易误归类为欺诈交易的比例:
= FN/(FN+TP)
= 477(477+18723)= 0.0248

下面我们计算每一类在计算经验风险和分类成本时使用该信息的比例。接下来:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

***—总体分类误差(或“经验风险”)😗两个类别中错误分类数据点的百分比。表示如下:
= prop 0 * Type I+prop 1 * Type II
=(FP+FN)/(TP+FP+TN+FN)
= 0.0257

在将成本分配给第一类和第二类错误(C0 分别=100 和 C1=1)的情况下,经验分类成本将计算如下:
= C0 * prop 0 * type 1+C1 * type II
= 100 * 0.0099 * 0.1146+1 * 0.9901 * 0.0248
= 0.1380

— F-score 是处理不平衡分类问题时的常用指标。它来源于测量精度和召回率;他们的计算见下表 3。如果相应的精度或召回率未定义或等于 0,则 F-score 被设置为 0。

o Precision: 测量您的模型根据其预测的标识(即正确和不正确的预测)对每个类做出正确预测的次数。

o 回忆: 测量你的模型在每一类的识别中做出正确预测的次数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 3:混淆矩阵与表 2 相同,只是它显示了如何计算精确度、召回率、&风险

使用上述精度和召回率的计算,我们计算每个类的 F 分数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接收器工作特性(ROC)曲线是分类模型在区分阈值变化时识别阳性和阴性类别的性能的图示(见下图 2)。此外,它反映了第一类和第二类误差之间的权衡。随着我们成功地在数据中识别出更多的真阴性(欺诈),代价是将非欺诈记录误识别为欺诈(犯假阳性)。ROC 曲线下面积(AUC)是一个单一数字的汇总,它量化了模型在区分阳性和阴性类别方面的表现。它通常介于 0 和 1 之间。该值越大,模型的性能越好。值 0.5 并不比随机猜测更好。如下图 2 所示,ROC-AUC 为 0.9734907,这表明该模型在识别欺诈交易和非欺诈交易方面做得很好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2:CS 范式下对原始数据进行逻辑回归得到的 ROC-【LR+原始】-

精确召回(PR) 曲线及其 AUC(PR-AUC)是处理不平衡数据时的替代指标。在图 3 中,欺诈类的 PR-AUC 为 0.857943,非欺诈类的 PR-AUC 为 0.9995953。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

****图 3: PR 曲线-“LR+原始”- 源自 CS 范式下对原始数据的逻辑回归

总之,对于第一类和第二类错误、经验风险和经验分类成本,较小的值表明分类模型的性能较好。然而,对于 F-score、ROC-AUC 和 PR-AUC,较大的值表明性能较好。

六。结果和解释

为了稳定我们的结果,该过程重复 50 次,并报告三种分类范例下所有分类器的平均性能(评估度量的平均值)。结果总结在图 4 至 7 和表 4 至 6 中。

经典分类(CC)范式

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4:经典分类范式下的度量结果

图 4(上图)展示了在 CC 范式下将每种重采样技术与分类模型配对的结果。我们观察到,没有重采样的所有分类器的经验风险比所有重采样技术的风险更小(更好)。此外,对于没有重采样技术的所有分类器,F 分数也更好(更高)。因此,我们得出结论,如果我们的学习目标是最小化风险(在 CC 范式下操作),则对原始数据应用 XGBoost 分类模型而不执行重采样技术是最佳选择(“XG b+原始”)。

值得注意的是,最小化不平衡数据上的总体分类误差可能会导致大的 I 类误差,这在上面清楚地示出了。然而,通过利用重采样技术,我们可以更好地控制 I 型误差。

为了方便读者,我们根据几个评估指标总结了 CC 范式下重采样技术与分类模型的最佳组合:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 4:CC 范式下的最佳组合

图 5(下图)中的 ROC-AUC 和 PR-AUC 测量了整体模型的性能,无需指定分类范例。这些指标表明 XGBoost 在所有重采样技术中效果最好。然而,根据 ROC-AUC,重采样技术不能改善逻辑回归的性能。然而,在 ROC-AUC 和 PR-AUC(非欺诈类)下,它们可以显著地有益于支持向量机。最后,以 ROC-AUC 和 PR-AUC(非欺诈类)为标准,“XGB+Hybrid”为最优组合,以 PR-AUC(欺诈类)为评估标准,“XGB+SMOTE”为最佳组合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5: ROC-AUC、PR-AUC(欺诈)和 PR-AUC(非欺诈)

成本敏感(CS)学习范式

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6:CS 学习范式下的指标结果

如果我们的目标是最小化总的错误分类成本,那么我们应该在 CS 学习范式下操作。从上面的图 6 中,我们发现,通过使用 I 型误差作为评估指标,所有模型都显著受益于重采样技术。下表通过对不同指标的评估,总结了 CS 学习范式下重采样技术与分类模型的最佳组合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 5:CS 学习范式下的最优组合

尼曼-皮尔逊范式

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7:尼曼-皮尔逊范式下的指标结果

如果我们的目标是最小化第二类错误,同时将第一类错误控制在目标水平之下,那么我们应该在 NP 范式下操作。其结果如图 7 所示。我们观察到,在重采样技术与分类模型的所有组合中,I 型误差在α下得到很好的控制。最后,我们在下表中总结了 NP 范式的最佳组合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 6:NP 范式下的最优组合

七世。最后备注&案例研究的局限性

当处理不平衡数据时,关键是要先问自己,在你的问题中,哪种错误的代价更大:第一类还是第二类?这个问题将帮助您确定合适的分类模式。一旦您确定了合适的范例,请从这里给出的图表中选择重采样技术和分类模型的最佳组合以应用于您的数据集。您的选择应该基于您想要用来评估分类器性能的评估度量。有几个可用的评估指标;选择一个你认为代价相对较高的错误。尽管如此,请记住,在我们的案例研究中,我们仅考虑了重采样技术和三种分类模型的选择性列表。还有很多其他的组合值得探索。另外请注意,在我们的案例研究中,我们随机选择了非欺诈类的子样本来构建我们的分类器,这对于我们的问题来说可能不具有代表性。

技术教程— R 代码

应用分类范例和重采样技术: 我们应用逻辑回归仅仅作为一个例子。

分类范例

1。经典分类范式

**## Training set
data_trainxy <- data.frame(train_x,train_y)## Testing set
data_testxy <- data.frame(test_x,test_y) ## Fit the model on the training set
model_cc = glm(train_y~.,family = “binomial”,data=data_trainxy)## Generate predictions on the testing set
prep_cc = predict(model_cc,test_x)
p_cc = 1/(1+exp(-prep_cc))## probability of Y=1 given X=x under testing set## Calculate the overall classification error (risk) on the testing set; set threshold=0.5threshold <- 0.5
pred_class <- ifelse(p_cc>threshold,”1",”0")
risk <- 1-mean(pred_class==test_y)**

2。 代价敏感学习范式(后处理方法)

**## Fit the model on the training set
model_cs = glm(train_y~.,family = “binomial”,data=data_trainxy)
prep_cs = predict(model_cs,test_x)
p_cs = 1/(1+exp(-prep_cs)) ## the probability of Y=1 given X=x under the testing set## Generate predictions on the testing set
threshold_cs = IR/(IR+1) ## IR is the imbalance ratio
pred_cs = ifelse(p_cs>threshold_cs,”1",”0")## Type I error on the testing set
ind0 = which(test_y == 0)
typeI = mean(pred_cs[ind0] != test_y[ind0])## Type II error on the testing set
ind1 = which(test_y == 1)
typeII = mean(pred_cs[ind1] != test_y[ind1]) ##Empirical misclassification cost on the testing set
m0 = length(which(test_y==0)) # samples size of Class 0 in test data
m1 = length(which(test_y==1)) # sample size of Class 1 in test data
cost = IR*(m0/(m0+m1))*typeI+1*(m1/(m0+m1))*typeII**

3。 Neyman-Pearson 范式(NP 伞状算法) 值得注意的是,在构造 NP 分类器时,我们只能对训练集的部分样本应用重采样技术。是因为背后的算法(NP 伞)把训练集的 0 类分成两部分:一部分拟合模型,一部分选择阈值。NP 伞状算法的细节可以在下面的论文“Neyman-Pearson 分类算法和 NP 接收器操作特征”中找到

**## Install library “nproc” package
install.packages(“nproc”, repos = “http://cran.us.r-project.org")
library(nproc)## Fit the model on the training set
fit = npc(train_x, train_y, method = “logistic”)## Generate predictions on the testing set
pred_np = predict(fit, test_x)## Compute type I error on the testing set
ind0 = which(test_y == 0)
typeI = mean(pred_np[ind0] != test_y[ind0])## Compute type II error on the testing set
ind1 = which(test_y == 1)
typeII = mean(pred_np[ind1] != test_y[ind1])**

重采样技术

1。 随机欠采样(“欠采样”)

**id0_train = which(train_y==0) ## index of class 0 in the training set
id1_train = which(train_y==1) ## index of class 1 in the training set
n0_train = length(id0_train) ## sample size of class 0 in the training set## Randomly sample observations without replacement from class 1
indexMaj = sample(id1_train,n0_train)## Obtain new training set
newtrain_under = data.frame(rbind(train_x[id0_train,],train_x[indexMaj,]), y=c(rep(0,n0_train),rep(1,n0_train)))**

2。 【过采样(SMOTE)】

**## Install library “smote” package
install.packages(“smote”)
library(smote)## Use SMOTE function to construct a new training set
geneData = SMOTE(train_x,train_y)## Obtain the new training set
newtrain_smote = geneData$data**

3。 混合: 这里它结合了“欠采样”和 SMOTE 重采样技术,最终训练集由以下内容组成:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**## Calculate the new sample size of the new training set
n0_train = length(id0_train) ## sample size of class 0 in the training set
n1_train = length(id1_train) ## sample size of class 0 in the training set
n_h = floor(n1_train/n0_train)*n0_train## Use SMOTE function to generate new data for class 0
M = n_h/n0_train-1
geneData_h = SMOTE(train_x,train_y,dup_size = M)
newtrain_hybrid0 = geneData_h$data[which(geneData_h$data$class==”0"),]
d=dim(newtrain_hybrid0)[2]## Randomly sample observations without replacement from class 1
indexMaj_h = sample(id1_train, n_h)## Obtain the new training set with hybrid method
newtrain_hybrid =
data.frame(rbind(newtrain_hybrid0[1:d,],train_x[indexMaj_hybrid,]),
y=c(rep(0,n_h),rep(1,n_h))) #the final training set consisting of n_h class 0 and n_h class 1 observations**

最后请注意,ROC-AUC 和 PR-AUC 可以分别通过“PRROC”包中的“roc.curve”和“pr.curve”函数计算。对于其他评估指标,您可以简单地使用这里包含的公式来计算它们。

非常感谢辛彤博士教授的友好和持续支持!

当细节很重要时,不平衡的数据

原文:https://towardsdatascience.com/imbalanced-data-when-details-matter-16bd3ec7ef74?source=collection_archive---------51-----------------------

当在你的数据集中找到一个值得信赖的政治家就像大海捞针一样困难时,你可以这么做。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

标准技术的插图,作者提供的图像

定义不平衡数据

当我们谈到不平衡的数据时,我们的意思是至少有 被低估。例如,在考虑构建分类器的问题时,我们称之为 idealistic-Voter。我们给它的任务是找出美国公众认为值得信任的政治家。当查看数据集时,我们意识到几乎每个样本都非常不受欢迎。

在术语分类中,我们称样本很少的类为少数类,样本很多的类为多数类

那么问题是什么呢?

让我们假设有 100 个政治家,其中只有一个被广大公众认为是值得信任的;我们就叫他亚伯拉罕吧。我们现在可以迅速建立一个理想的选民。通过简单地说“所有的政客都是骗子”,即把所有的政客都归类为不可信的,这就达到了 99%的准确率。损失会很低,我们可以做一个很好的演示,展示我们的理想主义者在最常见的指标上的得分有多高。

PRECISION = TP / (TP+FP) = 99%
ACCURACY = TP / (TP + FN) = 99 %
F1 = (2*PRECISION*RECALL)/(PRECISION+RECALL) = 99.5 %

但这不是目标!我们想要的是把好的和坏的分开,我们真的没有分开任何东西。那么我们如何发现我们有问题呢?我们对亚伯拉罕不公,我们都知道他不喜欢不公…

平衡指标

每当您处理不平衡的数据时,也要养成查看平衡指标的习惯。他们做的和你熟悉的那些一样,但是另外,他们取所有类的平均值。

BALANCED_PRECISION=(P_TRUSTWORTHY + P_UNTRUSTWORTHY)/2=50%

在这种情况下,另一个非常有效的指标是与真阳性率相比的假阳性率。在多标签的情况下,你通常会选择一些宏观平均分数。

我们意识到我们有一个问题,我们如何解决它?

上采样和下采样

让理想主义选民自己解决问题的最简单的方法可能就是给他提供更合理的选择。这意味着要么收集更多的数据,要么使用可爱的上采样技术。

这项技术的工作原理是,我们克隆我们敬爱的亚伯拉罕,这意味着我们复制了少数民族的成员。一旦我们将数据集平衡到一个足够的程度,我们会注意到我们的模型实际上必须学习一些东西来获得一个好的分数!

向下采样

与上采样相反的是下采样,也称为欠采样。如果您有足够多的数据来完成您的工作,这种技术是非常棒的(这从未发生在我身上,但我假设这个世界的大数据收集者有时可能处于这种位置)。

在这种情况下,您可以消除一些**多数类的实例。**你不必对半分,但足以让理想主义者有动力去学习一些东西。这同样适用于我们今天讨论的所有技术。

生成合成样本

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

生成合成示例,图片由作者提供

好了,现在我们开始讨论一些很酷的事情。我们凭空生成数据怎么样?我们加点亚伯拉罕和酷酷的电子眼镜怎么样?他肯定会同样值得信赖,而且还会赢得年轻人的选票!

加入一点ϵps

假设我们的数据集具有特征年龄。我们可以清楚地看到,唯一值得信赖的政治家是2020–1809 = 211岁,1809 年是亚伯拉罕的出生年份。但是那些有着同样成就但年龄分别为 211.001 岁和 210.999 岁的政治家呢?

大概一样吧!但是使用这种技术时要非常小心,因为你实际上是在伪造数据。这种技巧很容易适得其反,只有当你非常确信这是正确的选择时,才应该使用它。但是这给我们带来了一个稍微复杂一点的自动化技术。

重击

SMOTE 代表合成少数过采样技术。它通过仔细观察所有样本的属性来构造新样本。然后,它继续修改这些值,使它们保持在我们的少数类中观察到的范围内。听起来很复杂,我们来看一个简单的例子,它应该会变得像你的鼠标点击拍手一样清晰。让我们假设把 JFK 加入到数据集中,再来看看值得信赖的政治家的时代。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

SMOTE 插图,作者图片

如我们所见,标示为 SMOTE SAFE 的区域是我们可以自由生成新合成样本的区域!你可以在这里找到更深入的解释。这很吸引人,但我认为最重要的是知道这种方法的存在。

发挥创造力

我们可以在自动驾驶场景中找到一些令人难以置信的这种技术的例子。虽然该领域的所有主要竞争对手都已经收集了数 Pb 的数据,但像孩子跑在汽车前面这样的情况应该在实际遇到之前进行测试。这些情况也可能很少发生,以至于你永远找不到足够的训练数据。

必须生成合成数据,以便在许多不同的光照和天气条件下测试此类和各种其他边缘情况。人们经常使用 GAN 或类似的网络将已经存在的样本转换成各种其他形式,例如在冬天或下雨时。有多种方法可以做到这一点。可以在这里看一个说明这一点的短视频(我不隶属于他们也不知道他们有多好,但是他们有一个很优秀的短视频;)

演示合成数据生成的视频

改变损失函数

但是我们还有一样东西!如果我告诉你,我们可以在算法的核心——损失函数——处理问题,而不是在数据层面。

多年来,人们提出了许多方法,但没有一种方法是放之四海而皆准的。这通常很大程度上取决于识别**少数类、**的重要性,以及当你将样本错误分类为多数类时会产生什么样的成本。

加权损失函数,自己定义

混合这种损失的一种方法是简单地将发生少数类的项乘以常数> 1。这实际上是鼓励模型更多地关注少数民族的实例。在 Keras 中,这是内置的,可以轻松应用

class_weights = {0: 1.,
                1: 50.}
model.fit(X_train, Y_train,class_weights=class_weights)

在这个特殊的例子中,它告诉 Keras,应该将类 1 的一个实例视为类 0 的 50 个实例。在一些简单的 python 伪代码中,我们可以把它想成这样

def loss_weighted(x,y_true):y_pred=model.forward(x)
    if y_true==1:
        return 50*loss(y_pred,y_true)
    elif y_true==0:
        return 1*loss(y_pred,y_true)

类别平衡损失

随着类的数量变得越来越大,显式地定义东西就变得很乏味,就像我们上面做的那样。为此,提出了多种解决方案,其中最著名的是“基于有效样本数的类平衡损失

他们实际上提出的是重新加权损失函数。作者这样做是为了考虑每类样本的有效数量。为了控制损失在平衡的哪一侧结束,可以另外用超参数来调整它。

虽然这是对他们过程的一个非常简单的看法,但我觉得它抓住了最重要的方面,值得你记住。如果您曾经遇到过这样的情况,您有许多类,并且这些类之间存在明显的不平衡,那么一定要尝试一下这种方法。

结论

恭喜你,你现在知道当你遇到不平衡的数据时你能做什么了。有几种方法,为您的问题选择正确的方法并不总是一件容易的事情。这将在很大程度上取决于你的业务需求,以决定你想要投入多少时间和资源来更公平地平衡事情。意识到潜在的解决方案是解决它们的第一步!

如果你喜欢这篇文章,我会很高兴在 Twitter 或 LinkedIn 上联系你。

一定要看看我的 YouTube 频道,我每周都会在那里发布新视频。

电影数据科学-使用 Python 提取和分析 IMDb 数据

原文:https://towardsdatascience.com/imdb-data-science-pull-analyze-movies-data-using-python-b59dc8511157?source=collection_archive---------14-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

雅各布·欧文斯的电影来自 Unsplash

IMDb (互联网电影数据库)是最被认可的名字之一,因为其全面的在线数据库收集了电影、电影、电视剧等。截至今天(2020 年 7 月),你将通过以下数据看到 IMDb 数据库拥有大约700 万本图书。在本文中,我将使用 Jupyter 笔记本 中的 Python 来演示从哪里拉数据,如何快速解读数据,并回答一些有趣的问题,包括

kind 数据库涵盖哪类数据?

-一般情况下人们会给出什么样的评分?真的是正态分布吗?哪些电影收视率最高?

-根据我喜欢的电影,我还应该检查哪些电影?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一些主要的 IMDb 维度

加载 IMDb 数据库

IMDb 已经在 IMDb 网站上向公众及其客户提供了其数据库的基本子集供非商业使用,在那里你也可以找到相应的 IMDb 数据字典中描述的所有相关细节。在这个分析中,我主要关注 2 个数据集( title.basicstitle.ratings ),它们分别提供了 9 个和 3 个特征,包括标题 ID、名称、类型、成人电影标志、类型、评级和标题获得的投票数。

basics_tsv_file =”C:\\Users\....\Downloads\\basics.tsv”
basics = pd.read_csv(basics_tsv_file, sep=’\t’,low_memory=False)ratings_tsv_file = "C:\\Users\....\Downloads\\ratings.tsv"
ratings = pd.read_csv(ratings_tsv_file, sep='\t',low_memory=False)data = pd.merge(basics, ratings, on ="tconst")

当您通过唯一的 IMDb 头衔 id(t const)提取这两个数据集时,您会注意到这两个数据集的大小相差 7 倍:

  • title.basics700 万个头衔,但是
  • 片酬只有100 万片酬

但是当你合并这两个数据集时,你会发现合并后标题的数量并没有减少。这意味着 title.ratings 中包含的所有标题实际上都是 title.basics 中标题的 子集*;这是一个好消息,因为这意味着所有带有评级的图书都有基本信息。在这里,我不会进入细节,但我正在进行另一项工作,我将应用主成分分析,这是最有用的无监督机器学习技术之一,以深入了解什么样的电影往往没有评级数据。*

这样,如下所示的合并数据集有100 万个标题和 11 个维度,可以应用各种分析工具:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

按标题合并基本数据和评级数据集

标题的类型和流派

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

IMDb 瓷砖类型的饼图分布

顶级类型(电视剧、电影和短片)的帕累托 80/20 法则

对于瓷砖类型帕累托 80/20 法则在这里绝对成立。总共有 10 种不同的标题类型,其中标题数量最多的是电视剧集(几乎占标题的一半),其次是电影和短片。这三种类型合计占总标题数的 80%以上。另一方面,总片头数最少的后 3 种类型(电视短片、电视特辑和电视迷你剧)占片头总数的比例不到 10%。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

IMDb 流派的饼图分布

在过于复杂的分类中,顶级类型是喜剧、戏剧和纪录片

对于 T21 的瓷砖种类,IMDb 有一个长长的单子,上面有将近 2000 种不同的种类。正如你所看到的,类型的分布有一条长尾,其中只有前三种类型(喜剧、戏剧和纪录片)的份额超过 5%,但所有其他类型的份额都不超过 3%。

注意 长尾可能是由于在不同流派中过于复杂的分类造成的。例如,虽然“喜剧”占 9%,但有许多相似但略有不同的类型,如“喜剧,戏剧”(2%),“喜剧,短片”(2%),甚至“冒险,动画,喜剧”(1%)等,每个都占据了一些可以被归类为“喜剧”的份额。更不用说一部电影如何能被严格归类为“冒险、动画、喜剧”,而不是简单的“动作、冒险、动画”或“喜剧”

x 级电影

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

成人电影与否的饼状图分布

IMDb 数据库里没有多少 X 级电影

IMDb 有一个“成人”因子,它是基本数据集中的一个布尔(0/1)变量,标记出 18 岁以上的成人电影。从上面的饼状图来看,IMDb 数据库中的成人电影数量最少,仅占总数量的 1.8%。

*(注意在进行分析之前将 dtype对象转换为布尔作为默认 dtype 可能会误导进一步的分析)

等级

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

按瓷砖类型划分的平均 IMDb 评级分布

平均评分是 7 分左右。人家在给评分方面很大方!

下面的方框图有助于描述每种标题类型之间和内部评级分布的差异。首先,有趣的是,我们看到的不是正态的高斯分布,而是总体上非常向右倾斜。典型的中等平均评级是 7 左右,而不是 5 的中等评级。

电视剧的收视率比电影高得多

此外,在十个标题类型中,与电影相比,电视剧的收视率总体较高,变化较小,这带来了一个有趣的问题:这真的是因为电视剧的质量明显优于电影吗?人们倾向于对电影持更高的标准和更挑剔的态度吗?这些都有待回答,但可以肯定的是,如果你看到一集收视率为 7,它可能只是一个平均系列。另一方面,一定要去看一部评分为 7 的电影!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来自 UnsplashFlorian Olivo 的 HTML 代码

我对 IMDb 数据的初步探索到此结束,它涵盖了我在开始分析时想到的大多数问题。下一步,我会做进一步的分析,看看我上一个关于哪些电影会让我更感兴趣的问题,一旦有了,我会和你分享。

你可以在 Python Jupyter 笔记本的 GitHub 上的这里找到完整的代码

我希望你喜欢这篇文章,并从中学到一些有趣的东西。如果你有任何问题或想法,关于什么可能是有趣的进一步挖掘,请随时鼓掌和评论。谢谢!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由Courtney hedgeUnsplash 上拍摄

对电影评论进行情感分析

原文:https://towardsdatascience.com/imdb-reviews-or-8143fe57c825?source=collection_archive---------10-----------------------

TD-IDF 和 scikit 令牌化的要点-学习

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由杰克·希尔斯Unsplash 拍摄

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

**IMDb:**一个与电影、电视节目、家庭视频、视频游戏和在线流媒体内容相关的在线数据库,包括演员、制作人员和个人传记、情节摘要、琐事、粉丝和评论以及评级。

1.简介和导入数据

在本文中,我将使用 IMDB 电影评论数据集进行研究。该数据集包含 50,000 条评论,其中包括 25,000 条正面评论和 25,000 条负面评论。在图 1 的中可以看到评论的示例,其中用户给奥斯卡获奖电影《寄生虫》(2020)给出了 10/10 的评分和书面评论。

星星的数量可以很好地代表情感分类。例如,我们可以预先分配以下内容:

  • 10 颗星中至少有 7 颗= >阳性(标签=1)
  • 10 颗星中最多 4 颗= >阴性(标签=0)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

IMDB 用户评论对电影《寄生虫》( 2020)给予了积极评价

对我们来说幸运的是,斯坦福大学的研究人员已经完成了对评论数据集进行情感分类的“繁重”工作(详情请参考引文&参考文献)。这是数据集外观的剪贴画:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

包含“文本”和“情感”列的数据集

为了训练,我们的特征矩阵非常稀疏,这意味着在这个矩阵中有许多零,因为有 25,000 行和大约 75,000 列。因此,我们要做的是找出每个特征的权重,并将其乘以相应的 TD-IDF 值;将所有的值相加,通过一个 sigmoid 激活函数,这就是我们最终得到逻辑回归模型的方法。在这种情况下应用逻辑函数的优点是:该模型可以很好地处理稀疏矩阵,并且权重可以被解释为情感的概率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

逻辑回归模型的 Sigmoid 函数

2.将文档转换成特征向量

下面,我们将调用 CountVectorizer 上的fit_transform方法。这将构建单词袋模型的词汇,并将下面的示例句子转换为稀疏特征向量。

import numpy as npfrom sklearn.feature_extraction.text import CountVectorizercount = CountVectorizer()docs = ([‘The sun is shining’,‘The weather is sweet’,‘The sun is shining, the weather is sweet, and one and one is two’])bag = count.fit_transform(docs)print(count.vocabulary_)print(bag.toarray())

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

请注意词汇表现在是如何存储在 Python 字典中的,每个惟一的单词都映射到惟一的整数索引。该数组显示每个唯一单词的词频。

3.使用术语频率-逆文档频率的单词相关性(TD-IDF)

TD-IDF 可用于降低特征向量中频繁出现的单词的权重,例如,上面示例句子中的单词“is”。TD-IDF 可以通过术语频率与逆文档频率的乘积来计算。计算 TD-IDF 的公式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源于 hackernoon

我们现在将通过实例化TdidfTransformer 方法来转换上一节的原始频率输入,以获得我们的 TD-IDF 值。

from sklearn.feature_extraction.text import TfidfTransformernp.set_printoptions(precision=2)tfidf = TfidfTransformer(use_idf=True, norm=’l2', smooth_idf=True)print(tfidf.fit_transform(bag).toarray())

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

显然,从示例句子来看,单词“is”在文档的第三个句子中出现频率最高。在该值被转换为 TD-IDF 值后,您会注意到,现在不是夸大的值 3,而是 0.45。这是因为‘is’这个词也包含在文档的句子 1 和 2 中;因此不太可能包含任何对我们的模型有用的或歧视性的信息。

这就是 TD-IDF 值的核心思想——它们将文本数据转换为数值,并根据文本数据语料库中单词的频率对单词进行适当加权。

4.数据准备:预处理

在本节中,我们将定义一个助手函数来预处理文本数据,因为我们的评论文本可能包含特殊字符— html 标签、表情符号—我们希望在训练模型时考虑这些字符。

import redef preprocessor(text):text =re.sub(‘<[^>]*>’, ‘’, text)emoticons = re.findall(‘(?::|;|=)(?:-)?(?:\)|\(|D|P)’, text)text = re.sub(‘[\W]+’, ‘ ‘, text.lower()) + ‘ ‘.join(emoticons).replace(‘-’, ‘’)return textpreprocessor(“This is a :) test :-( !”)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如上图所示,在应用了定义好的preprocessor函数后,示例语句被去除了特殊字符;表情符号也被移到了句子的末尾。这是为了让我们的模型可以利用文本的顺序,还可以确定句子结尾的表情符号的情感。

5.文档的标记化

**在本节中,我们将把我们的数据表示为单词或标记的集合;我们还将执行单词级预处理任务,如词干提取。为了实现这一点,我们将利用自然语言工具包,或 nltk。

词干分析是一种将一个普通单词的屈折形式,有时是派生相关形式,简化为基本形式的技术。例如,单词“organizer”和“organizing”源于基本单词“organize”。因此,词干提取通常被称为一种粗略的启发式过程,即“砍掉”词尾,希望在大多数情况下正确实现目标——这通常包括去除派生词缀。

from nltk.stem.porter import PorterStemmerporter = PorterStemmer()def tokenizer(text):return text.split()tokenizer('runners like running thus they run')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

tokenizer函数将文本转换成令牌

def tokenizer_stemmer(text):return[porter.stem(word) for word in text.split()]tokenizer_stemmer(‘runners like running thus they run’)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

tokenizer_stemmer功能去掉了派生词缀

6.将文本数据转换为 TD-IDF 向量

我们已经在之前的示例文档中完成了这种 TD-IDF 转换,但是现在我们将fit_transform 我们的电影评论数据集填充到 TD-IDF 值中。然而,我们没有将这个过程分成几个步骤——将文档分成词频,然后将它们转换成 TD-IDF 值——而是实现了一个方法TfidfVectorizer ,该方法在一个单独的步骤中执行上述所有步骤。

from sklearn.feature_extraction.text import TfidfVectorizertfidf = TfidfVectorizer(strip_accents=None,lowercase=True,preprocessor=preprocessor, # defined preprocessor in Data Cleaningtokenizer=tokenizer_stemmer,use_idf=True,norm=’l2',smooth_idf=True)y = df.sentiment.valuesX = tfidf.fit_transform(df.review)

7.使用逻辑回归的文档分类

使用 X 和 y 分别作为我们的 TD-IDF 值的特征矩阵和情感值的目标向量,我们准备将我们的数据集分成训练集和测试集。然后,我们将把我们的训练集放入逻辑回归模型中。

请注意,我们不是手动调整我们的模型的超参数,而是使用LogisticRegressionCV来指定我们想要调整超参数的交叉验证折叠数——即 5 重交叉验证。

from sklearn.model_selection import train_test_splitimport picklefrom sklearn.linear_model import LogisticRegressionCVX_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1, test_size=0.5, shuffle=False)clf = LogisticRegressionCV(cv=5,scoring=’accuracy’,random_state=0,n_jobs=-1,verbose=3,max_iter=300).fit(X_train, y_train)

8.模型评估

最后,我们将传递我们的测试数据——我们的模型以前没有见过的数据——来推断我们的模型做得有多好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

准确度分数

89.6% —考虑到我们在研究中使用了一个相对简单的模型,这已经很不错了!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

混淆矩阵

另一种观察我们的分类器准确性的方法是通过混淆矩阵**。**

观察第一排。第一行是测试集中实际情感值为 1 的评论。你可以计算出,在 25000 条评论中,12473 条评论的情感值是 1;在这 12,473 个中,分类器正确地预测了其中的 11,209 个为 1。

这意味着,对于 11,209 条评论,测试集中的实际情感值为 1,分类器也正确地预测了这些值为 1。然而,虽然 1264 条评论的实际标签是 1,但分类器预测它们是 0,这相当不错。

情感值为 0 的评论怎么办?让我们看看第二排。看起来总共有 12,527 条评论的实际情感值为 0。

分类器将其中的 11,193 个正确预测为 0,将其中的 1,334 个错误预测为 1。因此,它在预测情感值为 0 的评论方面做得很好。

混淆矩阵的一个好处是它显示了模型正确预测或区分类别的能力。在二元分类器的特定情况下,比如这个例子,我们可以将这些数字解释为真阳性、假阳性、真阴性和假阴性的计数。

9.结论

在这项研究中,我们涵盖了以下主题:

  • 清理和预处理文本数据
  • 使用计数矢量化、术语频率和逆向文档频率、自然语言工具包等方法执行特征提取
  • 使用 scikit-learn 构建并采用了一个逻辑回归模型
  • 使用 Javan 的准确度分数和混淆矩阵进行模型评估

10.引用和参考文献

[1]安德鲁·马斯、雷蒙德·戴利、彼得·范、黄丹、安德鲁·吴和克里斯托弗·波茨。(2011).学习用于情感分析的词向量。 计算语言学协会第 49 届年会(ACL 2011)。

[2]用于 CSV 文件和笔记本的 Github 库:【https://github.com/TheClub4/IMDB_Sentiment_Analysis】T5

IMDB 电视节目数据分析:第 2 部分

原文:https://towardsdatascience.com/imdb-television-show-data-analysis-part-2-39ebf47977ff?source=collection_archive---------44-----------------------

IMDB 的电视节目分析。随着时间的推移,哪些流派流行?电视节目存在年龄歧视吗?节目评分存在性别偏见吗?现在有比以前更多的新节目吗?

要查看故事的原始版本,请点击此处

这篇文章是 IMDB 电视节目分析的第二部分。分析的第一部分涉及被高估/低估的电视节目,电视节目的一致性,以及节目是否被提前取消或走得太远,可以在这里找到。

在这篇文章中,我主要致力于回答 4 个问题——随着时间的推移,哪些类型变得越来越受欢迎或越来越不受欢迎,新电视节目的比例是否随着时间的推移而变化,领先年龄是否随着时间的推移而变化,以及在节目投票中是否存在性别偏见——更具体地说,针对女性的节目的投票是高于还是低于男性。

介绍

我先看一些探索性的图表,看看一段时间内的演出次数。在下面的图 1 中,可以看到这些年的节目数量一直增长到 2017 年。然而,有趣的是,2017 年之后,节目数量出现了小幅下降。直到 1990 年左右,增长趋势可以被看作是线性的,但此后演出的数量一直在以越来越快的速度增长。考虑到人们越来越容易接触到电视,以及网飞、亚马逊 Prime、Hulu 等流媒体服务的增加,这并不令人惊讶。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

随着时间的推移,哪些类型的节目增加了或减少了?

在这里,我想看看哪些类型在流行程度上发生了变化——根据那个时期电视节目总数的比例。在该数据集中,每个电视节目标题最多可以有 3 种类型。在下面的图 2a 中,箭头图示出了流派在 2000 年前后是如何变化的。真人秀从 2000 年前占全部节目的 1%左右增长到 2000 年后的 12%以上。纪录片和喜剧节目也增加了——尽管喜剧一开始就很高。家庭戏剧音乐流派按比例减少。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在下面的图 2b 中,我只比较了 2000 年之前和之后的几十年中最大的几十年,即 1990 年和 2010 年的几十年。我们看到类似于图 2a 中的真人秀喜剧家庭戏剧音乐的模式。但是,在这个对比中,我们可以看到纪录片也在往下走。动画游戏类节目在总节目中的比例也有所下降。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

随着时间的推移,新节目的比例有变化吗?

接下来,我会看看随着时间的推移是否会有更多的新节目出现,或者旧节目(前几年开始的)是否在数量上占主导地位。为此,我们可以使用电视节目数据或电视剧集数据。电视节目数据对每个节目的权重是相等的——而不是根据它们的集数,而电视集更多地捕捉了电视上的内容——就时间而言。新节目或新剧集被定义为第一年的电视节目或在节目开始的第一年播出的剧集。因此,举例来说,对于《绝命毒师》来说,2008 年是开始的一年,因此 2008 年出现的所有剧集都是新的。在这种情况下,这也正好是第一季,尽管这并不总是可以保证的——同一季可以跨越多年,也可以在同一年播出两季。对于 2009 年播出的剧集,*《绝命毒师》*不再算新剧,其剧集也不是新剧集。

在下面的图 3 中,我们可以看到新节目和剧集的比例。新节目的比例更加稳定,大部分保持在 45-55%的范围内。另一方面,新的剧集变化很大。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

除了 1980 年代早期和 1990 年代早期,新剧集的比例远远低于新剧集的比例。这表明,除了 20 世纪 80 年代初至 20 世纪 90 年代期间,第一年的节目与非第一年的节目相比,往往具有较低的集数。为了证实这一点,我在图 4 中将第一年的节目和非第一年的节目分组,绘制了平均剧集数。通过该图可以看出,除了在上述期间之外,第一年的节目确实比非第一年的节目具有更低的平均集数。一般来说,人们会认为第一年的剧集数量会更少,因为那时很多剧集可能会被取消。如果一个节目不好,很多时候它会被提前取消——所以这应该会降低第一年节目的平均水平。这也可能是因为电视迷你剧,因为它们只有一季长,而且往往比电视剧集数少。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,另一种查看电视节目在特定时间有多老的方法是绘制剧集年份和节目年份的平均差异。这用于定义季节编号,因为通常的季节编号在一年中可能会发生变化。同样,这可以使用剧集和电视节目数据来可视化。在下面的图 5 中,我们可以看到这个图。平均剧集年龄几乎一直呈上升趋势,2019 年是第六季(或 5 岁)。另一方面,一个普通的电视节目在 1990 年左右达到顶峰,最近在 2019 年,在第四季(或 3 岁)。同样,这种差异的原因可以基于图 4 来解释,因为第一季中的电视节目倾向于平均具有较少的剧集,较大的季剧集在剧集数据中过多地出现。从某种意义上说,电视剧数据每年只统计每部电视剧一集。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

随着时间的推移,提前期是否发生了变化?

在这一部分,我会看看男主角/女主角的年龄是否随着时间而改变。我们经常听到或读到好莱坞的年龄歧视。之前,已经使用 IMDB 数据集在这里寻找电影。

在下面的图 6 中,我们可以看到一些年龄歧视的证据,从 20 世纪 80 年代中期到 2000 年代末,随着年龄中位数的持续下降。通常情况下,随着电视节目年龄的增长,主角的年龄也会增加。因此,理论上,没有新的节目,铅的年龄应该增加。然而,在上面的图 3 中,我们注意到在任何一年都有大约 45-50%的新节目。自 2000 年代末以来,我们看到中值年龄的增长——尽管我们需要补充一点关于演员重用的警告,因为这些年来通常相同的演员是多个节目的一部分。因此,需要对趋势进行更长时间的观察。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来,在图 7 中,我比较了男主角和女主角的年龄差异。这些年来,男女主角的平均年龄相差 5-6 岁。2010 年,差距似乎在缩小。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

IMDB 评分是否存在性别偏见?

在此之前,在 IMDB 评级中寻找性别偏见的证据,首先我看了电视节目和剧集的数量及其在下图 8 中按领导性别划分的份额。电视节目的年轴是节目的开始年,而剧集的年轴是剧集的播出年。根据这两项指标,可以看出,自 20 世纪 60 年代以来,女性主演的电视节目比例一直在增加。有趣的是,根据剧集数据,由女性主演的节目几乎接近 50%,但根据电视节目数据,这一比例约为 40%。这表明,要么有女性主角的电视剧往往会有更多集,要么电视剧和各自剧集中定义的主角存在差异——这可能是像电视剧这样每集都有不同主角的情况。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在下面的图 9 中,我绘制了一段时间内(电视剧开始年份)按主角性别分组的电视剧集平均数量。我们可以看到,确实有女性主角的电视剧往往有更多的剧集。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,我研究了 IMDB 评级中是否存在性别偏见的证据。以前,人们曾讨论过男性会破坏针对女性的电视节目的收视率,而针对女性观众的电视节目在 IMDB 上的收视率往往较低。在这里,我控制其他变量的主机——如流派、季节数、集数、投票数、电视节目开始年份;寻找这种偏见的证据。

为了找出针对女性或男性的节目,我通过查看演员的排序,为女性导向的节目和男性导向的节目创建了一个代理变量。IMDB 数据集提供了这些信息。以女性为导向的节目被分类为主要演员为女性,或者前 2 名演员中的两名演员为女性,或者前 4 名演员中的大部分(即> = 3 名)为女性的任何节目。类似地,一个面向男性的节目被归类为应用相同的规则,但有男性演员。不符合这两种分类的电视节目被归类为中性的。这个规则被实验来复制寻找女性导向的节目组,在这里被识别为。虽然这一规则并不完美,但它可以消除很多误报(仅仅因为男主角是女性就被错误地归类为女性节目)。

我对收视率运行了一个线性回归模型,控制了一堆变量,除了这个节目是中性的,女性的,还是男性导向的。限于至少有 1,000 票的电视节目,针对女性的节目比男性节目低 0.19 分,中性节目低 0.11 分。看看至少有 5000 票的电视节目,女性节目的评分低 0.26 分,而中性节目低 0.16 分。最后,对于至少有 2 万票的节目,女性节目的评分低 0.34 分,中性节目低 0.17 分。所有这些影响都具有统计学意义(置信区间-99%)。

图 10 是一个交互式方框图(用点表示电视节目),按上述节目的性别分类分组。此图表仅包括投票数至少为 5000 且剧集评分中值大于 250 的剧集。可以看出,男性节目的平均收视率高于中性和女性节目——证实了女性节目收视率中的一些性别偏见。

注意:对于上面的互动图,将鼠标悬停在各点上以查看更多信息(如果在移动设备上,则点击)。框选允许放大,双击可将缩放重置为默认值。

IMDB 电视节目分析的第 2 部分到此结束。用于该分析的代码(和第 1 部分)可以在这里找到。分析的第一部分涉及被高估/低估的电视节目,电视节目的一致性,以及节目是否被提前取消或走得太远,可以在这里找到。

最初发布于https://sabnanih . github . io/blog/2020/06/26/IMD b-TV-Show-Analysis-part 2

IMDB 电视节目数据分析:第 1 部分

原文:https://towardsdatascience.com/imdb-tv-show-data-analysis-4961ef39d174?source=collection_archive---------57-----------------------

IMDB 电视收视率分析。哪些节目评价过高/过低,并且始终如一?哪部电视连续剧提前停播或播出时间过长?

这篇文章已被修改,以更好地适应中等。要查看故事的原始版本,请点击此处

在这篇文章中,我展示了使用 IMDB 数据对电视节目进行分析的结果。IMDB 是一个关于电影、电视节目、视频游戏等内容的大型在线数据库。对于这个分析,我主要关注电视连续剧、电视迷你剧和剧集的收视率。数据下载于 2020 年 5 月 14 日。完整的数据集文档可以在这里找到。在这篇文章的其余部分,我主要讨论 3 个问题——某些电视节目是被高估了还是被低估了,哪些电视节目是最一致或最不一致的,哪些电视连续剧取消得太早,哪些放得太久。

这是分析的第一部分。对于第二部分,其中包括对各种变量的分析,如流派、新剧集、年龄歧视和性别歧视的证据测试(男主角和女主角的节目),请点击此处

介绍

我首先看一些关于收视率分布的探索性图表。在下面的图 1 中,通过评级直方图可以看出,它们有些负偏,但大多数都在 6 到 9 之间。在受欢迎的电视节目(至少有 5000 票)中,分布更集中在 6-9 范围。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

某些电视节目被高估/低估了吗?

首先,我想比较节目收视率和剧集之间的差异。除了看节目收视率,我们还可以看他们剧集的收视率中值。理论上,这两个评级应该是接近的。因此,在下面的图 2 中,我创建了一个电视节目评分与剧集评分中位数的互动图,这些节目的投票数至少为 5000,剧集投票中位数至少为 250。这允许我们创建被低估和被高估的节目的定义——大部分剧集的评级低于节目评级的节目被高估,类似地,如果大部分剧集的评级高于节目评级,则被低估。在图 2 中,被高估的节目在绿色等价线上,被低估的系列在下面。我定义了一个简单的衡量节目收视率和剧集收视率之间偏差的标准(相对收视率偏差)。

δ (%) =(节目评级-中值剧集评级)/节目评级* 100 %

δ的较高正值意味着更多的高估,较低负值意味着低估。根据这个衡量标准,我们可以看到一些被严重低估的节目——蝙蝠女侠(δ=-71.43)罗斯威尔,新墨西哥(δ=-36.07)暗影猎手 (δ = -34.85)。同样,最被高估的剧集还有*《辛普森一家》(δ= 19.54)《恐怖大师》(δ= 16)《暮光之城》* (δ = 15)。

注意:对于所有交互式图,将鼠标悬停在各点上以查看更多信息(如果在移动设备上,则点击)。框选允许放大,双击可将缩放重置为默认值。

从图 2 中还可以看出,2000 年之前的电视节目具有更高的δ。在下面的图 3a 中,我观察了不同季节和年份组的δ变化。可以看出,在 2000 年之前开始的节目往往比最近的系列有更高的正偏差,而在几个季节中没有明显的偏差差异。2000 年之前,更高比例的节目被高估,2015 年之后,更高比例的节目被低估,而 2000-2014 年组似乎在δ = 0 左右对称。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

有趣的是,较老的节目往往显示更高的δ值。尚不清楚为什么会出现这种情况,但为了更仔细地观察,我在图 3b 中分别绘制了δ的两个分量。此外,由于在上面的图 3a 中没有明显的季数偏差,我将重点放在节目开始年份的偏差上。我们可以看到,在 2000-2014 年 post 2015 年后组中,电视节目收视率和中值剧集收视率都略高。然而,与其他年龄组相比,2000 年以前的节目具有最高的电视节目收视率和最低的剧集收视率中值。此外,多年来,剧集收视率中值似乎比电视剧收视率更稳定(总体变化较小)。也许老节目收视率更高的一个原因可能是怀旧——人们会更积极地记得以前看过的节目吗?IMDB 成立于 1993 年,互联网在 20 世纪 90 年代变得更加普及,因此一些老系列的投票者可能不会在投票时重新观看它。另一方面,剧集投票不会受到这种影响,因为人们通常不会像记住电视节目那样记住单个剧集。然而,这只是一种推测,基于现有的数据,它不是一个可检验的假设。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我还观察了不同类型的δ变化。IMDB 数据集中的每个标题最多可以与 3 个流派相关联。在下面的图 4a 中,我们可以看到动画纪录片节目与其他类型相比往往具有更高的δ,因此被高估了。请注意,由于每个电视节目可以有 3 种类型,异常电视节目在该图上最多可以用 3 个点来表示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

同样,不清楚为什么这两种类型的节目被高估了。所以,我想按流派来看看δ的成分。在图 4b 中,可以看出,跨流派的中值剧集评级相当相似,但是电视节目评级对于动画纪录片更高。因此,他们被高估的原因更多的是较高的电视节目收视率,而不是较低的剧集收视率中值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,我创建了一个交互式的情节,通过图 5 中的流派和电视节目开始年份来可视化δ。该图应用了抖动。我们可以将鼠标悬停在这些点上来查看有关电视节目的信息。类似于上面的图 4a,电视节目可以由该图上的最多 3 个点来表示。

哪些节目是最一致/最不一致的?

接下来,我看电视剧集的收视率一致性。为了衡量评级的一致性,我定义了一个相对标准差的简单度量。

η (%) =标准偏差事件评级/平均事件评级* 100 %

η值越高,意味着一致性越差。从下面的图 6 可以看出,剧集越多,η越高。除了迷你剧,最不一致的剧集还有*《你怕黑吗?(η= 24.72)《纸牌屋》(η= 18.56)《芝加哥医学》* (η = 15.97)。最符合的电视剧是像宇宙 (η = 1.14)和吉普赛 (η = 1.24)这样的较短的剧集。在至少 100 集的剧集中,交战规则 (η = 2.34)和 2 破财少女 (η = 2.66)最为一致。绿线具有回归斜率(总集数的η v/s 对数),而白线忽略倾向于具有较少集数的类型,如传记纪录片历史。我们可以看到,即使没有这些体裁,积极的关系仍然存在。这并不完全令人惊讶,更长的系列将有更多的机会出现异常事件(无论是积极的还是消极的),这往往会降低节目的一致性。

在下面的图 7a 中,我们可以看到根据评级和年份组的η变化。2000 年至 2014 年似乎与 2015 年至 2020 年非常相似。在 2000 年以前的群体中,我们看到更高的评级显示相对更一致。跨年度组比较,中低评级显示 2000 年前和 2000 年后的一致性较差。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2000 年前群体的模式看起来与其他群体不同。所以,我想检查一下剧集数量的差异是否能解释这种差异。在下面的图 7b 中,我们可以看到,图 7a 中具有较高η的这些组往往也具有较高的总发作值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

跨流派比较η,我们没有看到非常显著的变化,但是动画确实比其他流派有更高的η中值,并且传记纪录片历史更趋于一致。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一些类型更加一致的原因之一可能是这些系列通常比其他系列更短。因此,我通过类型和集数来观察电视节目的一致性。图 8b 是一个交互图,其中圆圈的大小与总集数成比例。我们可以看到传记纪录片历史往往也是集数较少。

这个系列是提前取消了还是持续了太久?

在这一部分,我通过电视连续剧来过滤标题,排除了只有一季的迷你剧。为了查看哪些剧集取消了早期 v/s 那些走得太远的剧集,我首先根据至少有 250 票的剧集的季数绘制了剧集评级。在下面的图 9 中,我们可以看到中值评级在 2-4 季左右最高,之后开始下降。第八季之后,降幅逐渐加大。基于此,一般来说,第二季和第四季之间的任何地方都是一部电视剧的理想长度。该图与基于 2013 年数据的图非常相似。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们也可以分别查看它们的峰值,而不是为所有系列定义一个共同的峰值。在下面的图 10 中,我创建了一个最终赛季中值收视率与旺季之前所有赛季中值收视率之间的互动图。一个系列的高峰被定义为具有最高中值收视率的季节。根据定义,因此所有一个赛季的系列都将位于绿色直线上,这表示最终赛季收视率和之前的最高收视率相等。图表上圆圈的大小与前后峰值额定值之间的绝对差值成比例。所以,持续时间太长的系列,要么有很大的圆圈,要么远远低于等值线。前一类中的一些系列是你怕黑吗?致命武器坏分子。来自后一类的有两个半男人Scrubs权力的游戏。《纸牌屋》属于这两类。《权力的游戏》第四季被热切期待,但最终令人失望。《纸牌屋》在最后一季的糟糕收视率可能与凯文·史派西扮演的角色在最后一季被移除有关——因为他被指控性行为不端。对于《Scrubs》,最后一季摆脱了前几季的大部分全职演员,更适合作为一个独立的衍生系列。关于结束得太早的系列,我们可以把它们算作有 1-2 个季节落在该线上或在峰值前大于 8.5 的范围内的系列。其中一些系列是宇宙:时空奥德赛福尔蒂塔宇宙(1980)萤火虫怪胎和极客也是在这种讨论中经常出现的系列之一。

注:本情节仅包括之前最高收视率至少为 7 的电视剧

最后,我查看了 100 个最受欢迎的完整系列的收视率范围。过去曾创建过类似的图此处的数据最后更新于 2017 年。这也可以让我们看到系列之间的一致性(如这里使用的)以及比较不同的系列和它们的结局如何。红点表示中间值、第一和第三四分位数,而蓝叉表示最终评级。大部分的系列都有很好的结局,但也有一些非常糟糕。中集与大结局收视率相差较大(大结局差于中集收视率)的剧集有德克斯特权力的游戏纸牌屋真爱如血好汉两个半

绝命毒师是为数不多的所有剧集评分都在 7.5 以上的剧集,也是唯一一集评分在 10 的剧集!《权力的游戏》实际上总体来说相当不错(最大值和第一个四分位数之间的差异非常小),但在最后一季中有一些非常差的剧集。部分全集都在 8 集以上的剧集有大谎言宇宙:时空奥德赛萤火虫怪胎和极客憨豆先生意中人罗马。在这组最受欢迎的节目中,穹顶之下是唯一一集收视率不高于 8 的剧集。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

IMDB 电视节目分析的第一部分到此结束。用于该分析的代码(和第 2 部分)可以在这里找到。第二部分包括随着时间的推移对各种变量的分析——比如流派、新剧集,以及对年龄歧视和性别分级歧视证据的测试(男主角和女主角的剧集)。

原载于https://sabnanih . github . io/blog/2020/05/25/IMDB-TV-Show-Analysis

冠状病毒对股票价格的影响

原文:https://towardsdatascience.com/impact-of-coronavirus-on-stock-prices-41c108c1ec65?source=collection_archive---------34-----------------------

了解一下武汉和欧洲爆发病毒以来,冠状病毒对股价的影响。

在这个故事中,我们将构建一个 Python 脚本来计算冠状病毒对股票价格的影响。我们将把意大利病毒爆发前的股票价格作为参考,并与几周后的相同股票价格进行比较。

我们将通过使用 Python 和 Pandas 计算多只股票的每日价格变化来实现这一点。我们的最终结果将显示在下面的数据框中,该数据框包含了相对于 2 月 21 日的股价百分比变化,2 月 21 日是意大利病毒大爆发的前一天。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Python for Finance —冠状病毒对股票价格的影响

冠状病毒对股票市场的影响

我们都知道这种病毒确实起源于 201 年 12 月的武汉。它迅速发展到其他国家,最终已经成为一个全球性的疫情。

就股市影响而言,我认为股市只是在意大利疫情爆发后才受到病毒的影响。让我们看看我的理解是否正确。

冠状病毒对股票市场的真正影响是什么?让我们构建一个简单的 Python 脚本来找出答案。

首先,我将选择 10 家公司进行分析。我选择了 10 家公司,这些公司是我之前一直在跟踪的潜在未来投资对象。自由地将你自己的公司添加到列表中。

我已经将这 10 只股票添加到一个名为 公司 的列表中。我们将对每个公司做的是:

  1. 财务 API 发出 http 请求 ,下载历史价格数据。API 通过创建一个免费账户提供 500 次免费的每日通话。
  2. 提取每家公司的 n 天历史价格,并将它们添加到熊猫数据框架中。注意:检查 API 历史价格端点以查看 API 响应的结构。
  3. 将每个股票数据帧连接成一个 s 单个数据帧
  4. 以冠状病毒在欧洲爆发的前一天为参考,计算价格变化。
import pandas as pd
import requests

#Store your API Key in demo. 500 free daily API calls
demo ='YourAPIKEY'

companies = ['HEAR','F', 'GOOG', 'MSFT', 'AAPL', 'IBM', 'ORCL','AMZN','BABA','JNJ']

#Create a empty list to later add each of the stock prices DataFrame
listofdf = []
# We will extract the latest 16 days of stock prices since it was when the virus outbreak started in Europe (i.e. 21st of February)
days = -16

#(1)
for item in companies:
    histprices = requests.get(f"https://fmpcloud.io/api/v3/historical-price-full/{item}?serietype=line&apikey={demo}")
    histprices = histprices.json()

    #Parse the API response and select only last n days of prices. 16 days in our example
    histprices = histprices['historical'][days:]

上面的代码所做的是提取包含在 公司 列表中的每只股票的历史价格。然后,我们解析 API 响应并提取最近的 16 天。

我们可以很容易地做到这一点,因为历史键中包含的响应是一个列表。因此,我们可以简单地对列表进行切片,以保留最新的 16 个元素,这 16 个元素代表最近的 16 个每日价格。下面是 API 响应的摘录,便于参考。

{
"symbol": "AAPL",
"historical": [
{
"date": "1989-09-19",
"close": 1.54
},
{
"date": "1989-09-20",
"close": 1.59
},
{
"date": "1989-09-21",
"close": 1.6
},...

从 API 中提取最近 n 天的 。我们可以 为每只股票 ( 2)创建一个熊猫数据帧。我们使用 pd。DataFrame.from_Dict 方法在我们的字典之外创建一个包含每日价格的 DataFrame。

最后,我们将每个股票数据帧添加到一个列表中。

for item in companies:
    histprices = requests.get(f"https://fmpcloud.io/api/v3/historical-price-full/{item}?serietype=line&apikey={demo}")
    histprices = histprices.json()
    histprices = histprices['historical'][days:]  
    #2
    histpricesdf = pd.DataFrame.from_dict(histprices)
     #rename column to the name of the stock
    histpricesdf = histpricesdf.rename({'close': item}, axis=1) 
    #append all dfs to list
    listofdf.append(histpricesdf)

将所有股票价格放在一起

现在,我们已经将我们的每只股票的价格放入一个熊猫数据框架中。但是,我们希望将所有公司的价格放在一个数据框架中。

我们可以很容易地将它们连接起来。首先,我们将日期设置为每个数据帧的索引。然后,我们可以使用 pd.concat 方法将它们放在一起:

#set index of each DataFrame by common column before concatinatinghtem
dfs = [df.set_index('date') for df in listofdf]

histpriceconcat = pd.concat(dfs,axis=1)

现在,如果我们打印histpricecontat,我们就有了一个漂亮的熊猫数据框架,其中包含了所选股票 的所有 日价格。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过考察个股价格,很难发现冠状病毒对股价的影响是什么。我们看到价格一直在下降,但看看正常化的结果会更有意思。

我们要做的是用第一行数据除每只股票的每日价格。在我们的例子中,这是 2 月 21 日,因为这是所有冠状病毒病例开始在意大利出现的前一天,这将是我们的参考:

histpriceconcat = histpriceconcat/histpriceconcat.iloc[0] histpriceconcat['mean'] = histpriceconcat.mean(axis=1) histpriceconcat

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

酷!现在,我们可以很容易地看到电晕病毒对股票价格的影响百分比。例如,我们看到像苹果这样的公司,在 3 月 13 日的收盘价比 2 月 21 日的价格低 12%(即 1–0.887941)。

同样,亚马逊的股价有 15%的折让,而中国公司阿里巴巴的股价只有 9%的折让。

意大利爆发前冠状病毒对股价的影响

显然,冠状病毒在欧洲的爆发对股票价格产生了影响。但是中间的那段时间呢?那是危机第一次从武汉开始,直到病毒到达欧洲?

我们可以通过重现 12 月 27 日到 2 月 21 日的分析来轻松检查影响。我们可以通过修改下面两行代码来实现这一点:

#-53 days is the 27th of December 2019
days = -53 
#-15 days is the 21st of February   
histprices = histprices['historical'][days:-15]

对于大多数股票来说,在欧洲几乎没有病例的情况下,病毒的爆发似乎没有对股价产生影响。在此期间,股票价格平均上涨了 2%。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

包扎

在这篇文章中,我们构建了一个很好的 Python 工具来计算多只股票的价格变化。我们这样做是为了分析冠状病毒对股票价格的影响。

如所选股票所示,似乎只有当病毒爆发到达意大利时,股票价格才开始下跌。然而,我想指出这种分析的一个局限性。我几乎只选择了美国股票。

对亚洲股票重复这一分析,看看结果是否会有所不同,将会很有意思。我把这个任务留给你。

很高兴在我的 Twitter 账户中听到您的回复。参见以下脚本供您参考。

原载于 2020 年 3 月 15 日【https://codingandfun.com】

#Price change
import pandas as pd
import requests

companies = ['HEAR','F', 'GOOG', 'MSFT', 'AAPL', 'IBM', 'ORCL','AMZN','BABA','JNJ']
listofdf = []
days = -16

for item in companies:
    histprices = requests.get(f"https://fmpcloud.io/api/v3/historical-price-full/{item}?serietype=line&apikey={demo}")
    histprices = histprices.json()

    #Parse the API response and select only last n days of prices
    histprices = histprices['historical'][days:]
    histpricesdf = pd.DataFrame.from_dict(histprices)
    histpricesdf = histpricesdf.rename({'close': item}, axis=1) 
    #append all dfs to list
    listofdf.append(histpricesdf)

#set index of each DataFrame by common column before concatinatinghtem
dfs = [df.set_index('date') for df in listofdf]

histpriceconcat = pd.concat(dfs,axis=1)
#divide all dataframe by first line of data to enable comparison
histpriceconcat = histpriceconcat/histpriceconcat.iloc[0]
histpriceconcat['mean'] = histpriceconcat.mean(axis=1)

histpriceconcat

新冠肺炎的影响-使用 Python 进行数据可视化

原文:https://towardsdatascience.com/impact-of-covid-19-data-visualization-using-python-6f8e3bdc860b?source=collection_archive---------43-----------------------

使用 python 在印度地图上可视化冠状病毒爆发的初级方法。当你读完这篇文章时,你将能够生成一个如下图所示的美丽的地图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

印度地图,每个邦都有标记,显示 COVID19 的最新统计数据。(图片由作者提供)

A.介绍

世界正在与一个看不见的致命敌人搏斗,试图了解如何应对冠状病毒带来的威胁。对于一些作家来说,唯一的出路是动笔,试图概念化和记录在国家被封锁、正常生活似乎已经停止的情况下继续生活的感觉。

“一幅画胜过千言万语”

正如引用的话所说,数据可视化有助于以更好的方式从数据源中获得信息洞察力。因此,通过这篇文章,我想展示一个人如何想象自己国家的地图,以及不同的行政区和社区如何受到这种可怕病毒的影响。

B.数据描述

为了开发这个应用程序,我们需要一些需要从网站废弃的数据

  1. 我们需要印度所有邦的经度和纬度坐标,我们可以使用 python 从 quicksgs.com 的中删除这些数据。
  2. 我们需要冠状病毒在该国各州的当前状态,我们可以使用 python 从维基百科中删除这些动态数据。

C.目标

显示印度各邦的住院人数、死亡人数、康复人数以及当前活跃病例。

D.建筑模型

  1. 数据收集
  2. 数据清理和准备
  3. 使用 folio(python 库)的数据可视化

让我们开始构建我们的应用程序…

D.1 .数据收集

  1. 导入所有重要的 python 库

2.从quicksgs.com刮取经纬度

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上述代码片段的输出(图片由作者提供)

3.从维基百科抓取印度各邦的实时电晕统计数据

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上述代码片段的输出(图片由作者提供)

如您所见,数据并不干净,不能直接用于构建应用程序,因此需要对其进行清理和格式化,以便与我们将要构建的应用程序兼容。

D.2 .数据清理和准备

清理坐标和 covid19 表,使其与应用程序兼容。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

已清理的坐标数据表(删除了度数符号)(图片由作者提供)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

清理了 covid19 表(更改了列名并删除了不必要的行)(图片由作者提供)

到目前为止,我们有两个表,一个包含纬度和经度坐标,另一个包含印度每个邦的 covid19 状态,所以最后我们在 state 列上创建了一个连接这两个表的表。

最终的表格看起来像

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是在印度地图上绘图所需的数据(图片由作者提供)

D.3 .可视化

现在我们开始最后一步,可视化这些数据!

我们使用叶子 (python 库)在印度地图上描绘以上所有数据。

万岁!我们已经用一种简单得多的方式完成了可视化,所以看一下我们的应用程序的输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者图片

因为我是印度的居民,我从各种网站上研究了印度各州和冠状病毒的统计数据,如果你不是印度人,你可以用你自己国家的数据替换数据来源。

结论

这篇文章给出了最好的和聪明的方法来形象化新冠肺炎是如何影响印度各邦的。由于我们将从维基百科中删除数据,我们将获得实时数据,所以我们的应用程序不会是静态的,而是每次维基百科更新他们关于冠状病毒的网站时都会发生变化。

参考文献:

  1. 维基百科(一个基于 wiki 技术的多语言的百科全书协作计划ˌ也是一部用不同语言写成的网络百科全书ˌ 其目标及宗旨是为全人类提供自由的百科全书)ˌ开放性的百科全书
  2. quickgs.com

你可以在这里 找到详细的代码

编者注: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

感谢阅读!😄

*** [## 我附近的热门地点—使用 Python 和 FourSquare API 的数据可视化

这篇文章教你如何在规定的范围内,将你附近所有受欢迎的地方形象化

towardsdatascience.com](/popular-places-near-me-data-visualization-using-python-and-foursquare-api-4d1683cd62d1)***

新冠肺炎对英国 BAME 人口的影响

原文:https://towardsdatascience.com/impact-of-covid-19-on-the-uk-bame-population-cc09244c5d63?source=collection_archive---------59-----------------------

使用公开数据描述新冠肺炎时期影响英国 BAME 人口的社会经济因素

“…病毒不分种族和国籍;它不能偷看你的驾照或人口普查表来检查你是不是黑人。社会检查它,并代表病毒提供鉴别。——游戏木——大西洋

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由塞缪尔·莱德Unsplash 拍摄

人们越来越担心冠状病毒对少数民族的影响更大。黑人、亚洲人和少数民族(BAME)社区占总人口的 14%,但占医院中重症冠状病毒患者的三分之一。英国公共卫生报告发现,新冠肺炎对所有非白人少数民族的影响不成比例。

这篇文章将超额死亡统计数据与公开的社会经济数据进行了比较,以描述英格兰和威尔士的情况。描述性分析使用 2011 年人口普查数据来确定地方当局的民族构成;一种类似于国家统计局使用的方法。因此,观察单位将是地方当局。可以在 GitHub 上找到并复制原始数据、转换和分析的完整分类。

编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里

这是怎么回事?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

地方当局种族占超额死亡的比例资料来源

上图显示了某个地方当局内发生的死亡人数与该地方当局中特定族裔的比例代表人数的对比。从左到右向上倾斜的线条表明,BAME 人口比例较高的地方当局的超额死亡人数较多。而向下倾斜的紫色线表明,种族多样性较低的地方当局看到的超额死亡人数较少。值得注意的是,数据确实聚集在接近 0 的位置,拟合这种聚集数据的回归线本身并不是关系的证据。这不是直接衡量对 BAME 社区的影响,而是比较受病毒负面影响更大的地理区域及其相应的民族构成。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

年龄

在我们研究影响病毒影响的特定地点因素之前,我们必须考虑患者的年龄,我们认为这是新冠肺炎死亡率的一个促成因素。国家统计局公布的数据包含英格兰和威尔士种族群体冠状病毒相关死亡的统计数据,并显示 88%的冠状病毒相关死亡是 64 岁以上的人。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

COVID 死亡人数和总人口资料来源

上图显示了所有记录的 covid 死亡的种族分类。有趣的是,这一分类与 2011 年人口普查统计非常相似,该统计显示 14%的人口是 BAME 人,covid 数据显示 16.2%的 COVID 死亡是 BAME 人。对 BAME 人口似乎没有不成比例的影响。

为了解决这个问题,我们可以使用 Dana Mackenzie 的博客帖子,通过辛普森悖论来研究美国的种族和 covid。在提出下面的因果模型时,他假设种族会影响活到 65 岁或更老的几率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这就形成了一个链条,因果可以通过这个链条。如果我们要问,种族【仅 对 Covid 死亡率有什么影响,那么我们必须保持所有其他变量不变。因此,我们应该控制年龄并按年龄划分,创建两个组“0-64”和“65+”:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不同年龄组按种族划分的 Covid 死亡人数资料来源

现在我们按年龄划分 COVID 死亡人数;这显示了 65 岁以上人群的类似分布。按照种族划分的 COVID 死亡人数大致符合 2011 年英国人口普查的种族划分;86%的英国人口是白人,65 岁以上的 Covid 死亡者中 85.7%也是白人。然而,对于 65 岁以下的年龄段,与联合王国人口相比,BAME 人的死亡率更高;64 岁以下的 covid 死亡中,30.7%来自 BAME 社区,相比之下,只有 14%来自人口。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

不同年龄组按种族划分的人口资料来源

最后,我们按照种族和年龄来划分人口,现在我们可以看到两个年龄段的种族之间的明显差异。现在,65 岁以下的 BAME 人口占了 30.7%的 covid 死亡,但只占总人口的 14.3%。2011 年人口普查显示,BAME 人口仅占 65 岁以上人口的 2.3%,但却占 COVID 死亡人数的 14.3%。这似乎表明对 BAME 人口的影响非常大。如图所示,不同的数据分组会导致不同的结果;在做出这些分组决策时,关于因果路径的假设是必不可少的。

地点:生活在城市

可能有一些内在/生理条件导致 BAME 人具有更高的风险,但这可能不是全部。多项流行病学研究承认,恶劣的生活环境会导致健康风险。Centric Lab 发布了一份深入研究人类健康和城市环境的报告。经济观察组织还详细描述了城市成为冠状病毒热点的机制,包括职业结构。这些研究支持下面列出的因果结构,其中种族将影响位置决策(移民定居在就业机会增加的密集地区),并且这些历史位置模式将代代相传。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了解开“高风险城市环境”的谜团,以下是使用公开可用数据获得的区域特定属性的相关矩阵。使用 Spearman 值和 p 值计算的相关性显示在这里

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

相关矩阵(Spearman) 来源

  • 超额死亡与 BAME 人口的增加呈正相关,与白人人口的增加呈负相关。和我们在第一张散点图中看到的一样。
  • BAME 种群的同处一地:图右下角的红色聚类表示 BAME 种群的同处一地。在少数民族比例较高的地方当局,其他少数民族的比例也往往较高。
  • 人口密度和 BAME 人口:人口密度是使用国家统计局人口估计值和地方当局的规模(然后与 GLA 人口密度估计值交叉引用)计算的。显示 BAME 族裔倾向于居住在人口更密集的地区。当结合政府发现少数民族居住在拥挤的住房;一幅 BAME 人口密集生活的画面出现了。
  • 超额死亡与 65 岁以上的人数较多呈负相关,而 65 岁以上的人往往人口密度较低,种族也较少。
  • 休假比例和多重剥夺指数:这两个指标都没有显示任何关系的真实迹象。

到目前为止,我们只看到了可能让我们了解高风险地方当局类型的相关性。到目前为止,没有使用花哨的建模或加权指标,这来自汤姆·福斯写的一篇关于有用的统计数据和误导性指标的文章。他研究了一个邻近的问题——最贫困的地区受到的影响更严重——但没有找到证据。我也发现贫困和过度死亡之间没有很强的联系。但是汤姆也强调了关于社会公正元素的重要一点;BAME 人正在受到影响,但为了揭示真正的潜在因素,我们必须在分析中不带偏见,而不是试图将数据纳入我们的信念,并松散地持有我们的假设。

到目前为止,数据收集已经优先用于监控,当试图“实时”发现因果联系时,这可能是一个问题;2011 年的人口普查数据离正式过时还有一年。收集和发布关于冠状病毒的数据是一个持续的、反复的过程;收集方法和数据质量可以每周改变。比如说;第二支柱测试的省略向我们展示了“数据”可以发生多么剧烈的变化。英国《金融时报》的克里斯·贾尔斯将新的快速经济数据比作快餐——对你来说很诱人,但很糟糕。依赖数据而不了解因果结构可能会产生误导。

地理空间分析

不缺少 COVID 地图仪表板;空间分析已经成为试图控制和减少传播的一个重要工具。下面的地图使用了当地的莫兰统计数据,即:“变量(如超额死亡)与其周围值之间关系的相关系数”。我们用这种方法来比较地方当局和邻近地方当局的超额死亡率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用当地莫兰统计数据的超额死亡人数来源

左侧的散点图显示了地方当局及其与邻居的关系,彩色圆点在统计学上显著性 p=0.05。右上角的红色象限显示,超额死亡人数高的 LA 被其他超额死亡人数类似的 LA 包围。而左下角的蓝色象限显示的是低超额死亡,周围是其他低超额死亡的 LA。

在地图上,红色区域表示“covid 热点”,我们看到利物浦和曼彻斯特周围的伦敦地方当局和地区集群被突出显示为与类似高邻居的高超额死亡人数。莱斯特和伯明翰附近也有一个集群,当地已经实施了封锁。

结论

相关矩阵显示了 BAME 人口在密集区域的共同位置,空间分析显示了城市地区高超额死亡的相关性-表明了城市在增加 COVID 中的作用以及更多的 BAME 人生活在城市中。然而,这种推理忽略了城市内部的不平等和两极分化。城市是非常不同的社会经济群体共同生活的地方。仅关注地区整体的分析和政策将忽略这些差异,而更精细的数据将有助于这一努力。

在这样的不确定时期,我们经常寻找数据来抓住不放,并提供一些确定性;但是更多关于我们世界的数据并不一定意味着我们更了解我们的世界。复杂的模型和机器学习不会清除数据中的错误和遗漏的测试数据,而是强化它们。这是第一次尝试了解 COVID 对英国 BAME 人口的影响。

在此期间,代码和数据(原始的和干净的)都是在线的。我知道所用的统计方法非常简单,并且相信这将有助于更好地传达信息,而不是隐藏意思(以及我的错误!)复杂建模和警告的背后。有时候简单比复杂的建模方法更清晰,在这个不确定的时代,清晰是供不应求的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值