Dario Radečić作者小舟编辑

M1芯片搞数据科学好使吗?5种基准测试给你答案

最近 M1 芯片爆火,它是否适用于数据科学?在常用基准上测试一下就知道了。

新版 Macbook 已经问世了一段时间,如果将 M1 芯片用于数据科学,性能会如何呢?本文作者将 M1 Macbook Pro 与基于 Intel 的 2019 Macbook Pro 在 5 种常用基准上进行了测试,结果发现 M1 芯片的性能确实是令人震惊的。

首先,它的运行速度比 2019 MBP 是快几倍的,并且运行过程中完全保持安静。我执行了多 CPU 的困难任务,散热扇甚至都没有发动过。当然,还有电池寿命也令人难以置信,重度使用多达 14 小时也不会出现问题。


测试的基准共有 5 种:

  • CPU 和 GPU 基准

  • 性能测试——纯 Python;

  • 性能测试——Numpy;

  • 性能测试——Pandas;

  • 性能测试——Scikit-Learn。


本文的所有比较都是在两个 Macbook Pro 之间进行的:

  • 2019 Macbook Pro(i5-8257U @ 1.40 GHz / 8 GB LPDDR3 / Iris Plus 645 1536 MB)——Intel MBP 13-inch 2019

  • 2020 M1 Macbook Pro(M1 @ 3.19 GHz / 8GB)——M1 MBP 13-inch 2020


并非所有库都与新 M1 芯片兼容。目前配置 Numpy 和 TensorFlow 没问题,但是 Pandas 和 Scikit-Learn 还不能在本地运行 - 至少我没有找到可用的版本。

唯一可行的解决方案是通过 Anaconda 安装这两个库,但需要通过 Rosseta 2 仿真器运行,因此它比本机要慢一些。

你将看到的测试在任何形式上都不是「科学的」。他们仅仅比较了上述机器之间在一组不同的编程和数据科学任务中的运行时。


CPU 和 GPU 基准

我们首先从基本的 CPU 和 GPU 基准开始。使用 Geekbench 5 进行测试的结果如下表:


图 1:Geekbench 比较(CPU 和 GPU)。

M1 芯片在 2019 Mac 中超越了 Intel 芯片。该基准测试仅衡量整体机器性能,与本文要进行的数据科学基准测试并不是百分百相关。


性能测试——纯 Python

以下是在该基准中执行的任务列表:

  • 创建一个包含 100 至 999 之间的 100000000 随机整数的列表 l;

  • 对列表 l 中的每个项目求平方;

  • 取 l 中每一项的平方根;

  • 将相应的平方和平方根相乘;

  • 相应的平方和平方根相除;

  • 对相应的平方和平方根进行整除运算。


该测试仅使用内置 Python 库,不含 Numpy。以下是测试的代码段


import random
   time_start = datetime.now()
   l = [random.randrange(100, 999) for i in range(100000000)] 
   squared = [x**2 for x in l]  
sqrt = [x**0.5 for x in l]  
mul = [x * y for x, y in zip(squared, sqrt)]  
div = [x / y for x, y in zip(squared, sqrt)]  
int_div = [x // y for x, y in zip(squared, sqrt)] 
   time_end = datetime.now()  
print(f'TOTAL TIME = {(time_end - time_start).seconds} seconds')

结果如下:

图 2:Python 速度测试,越低为越好。

通过 Anaconda(和 Rosseta 2)在 M1 Mac 上运行的 Python 减少了 196 秒的运行时。最好是在本地运行 Python,因为这样就能将运行时进一步减少 43 秒。


性能测试——Numpy

以下是在该基准中执行的任务列表:

  • 矩阵乘法

  • 向量乘法

  • 奇异值分解

  • Cholesky 分解

  • 特征分解


脚本如下

# SOURCE: https://gist.github.com/markus-beuckelmann/8bc25531b11158431a5b09a45abd6276
import numpy as np
from time import time
from datetime import datetime
start_time = datetime.now()
# Let's take the randomness out of random numbers (for reproducibility)
np.random.seed(0)
size = 4096
A, B = np.random.random((size, size)), np.random.random((size, size))
C, D = np.random.random((size * 128,)), np.random.random((size * 128,))
E = np.random.random((int(size / 2), int(size / 4)))
F = np.random.random((int(size / 2), int(size / 2)))
F = np.dot(F, F.T)
G = np.random.random((int(size / 2), int(size / 2)))
# Matrix multiplication
N = 20
t = time()
for i in range(N):
np.dot(A, B)
delta = time() - t
print('Dotted two %dx%d matrices in %0.2f s.' % (size, size, delta / N))
del A, B
# Vector multiplication
N = 5000
t = time()
for i in range(N):
np.dot(C, D)
delta = time() - t
print('Dotted two vectors of length %d in %0.2f ms.' % (size * 128, 1e3 * delta / N))
del C, D
# Singular Value Decomposition (SVD)
N = 3
t = time()
for i in range(N):
np.linalg.svd(E, full_matrices = False)
delta = time() - t
print("SVD of a %dx%d matrix in %0.2f s." % (size / 2, size / 4, delta / N))
del E
# Cholesky Decomposition
N = 3
t = time()
for i in range(N):
np.linalg.cholesky(F)
delta = time() - t
print("Cholesky decomposition of a %dx%d matrix in %0.2f s." % (size / 2, size / 2, delta / N))
# Eigendecomposition
t = time()
for i in range(N):
np.linalg.eig(G)
delta = time() - t
print("Eigendecomposition of a %dx%d matrix in %0.2f s." % (size / 2, size / 2, delta / N))
print('')
end_time = datetime.now()
print(f'TOTAL TIME = {(end_time - start_time).seconds} seconds')

测试结果如下:



图 3:Numpy 速度测试,越低越好。

在 Numpy 上得到的结果有点奇怪。Numpy 似乎在 2019 Intel Mac 上运行得更快,作者猜想原因可能在于进行了一些优化。


性能测试——Pandas

Pandas 基准非常类似于 Python。二者执行了相同的操作,但结果被合并为单个数据 frame。

以下是任务列表:

  • 创建一个空的数据 frame;

  • 为它分配含 100 到 999 之间 100,000,000 个随机整数的 column(X);

  • 将 X 中的每一项平方;

  • 取 X 中每一项的平方根;

  • 对应的平方和平方根相乘;

  • 对应的平方和平方根相除;

  • 对对应的平方和平方根执行整数除法。


以下是测试代码段:

import numpy as np  
  import pandas as pd  
  from datetime import datetime
   time_start = datetime.now() 
   df = pd.DataFrame()  
df['X'] = np.random.randint(low=100, high=999, size=100000000)  
df['X_squared'] = df['X'].apply(lambda x: x**2)  
df['X_sqrt'] = df['X'].apply(lambda x: x**0.5)  
df['Mul'] = df['X_squared'] * df['X_sqrt']  
df['Div'] = df['X_squared'] / df['X_sqrt']  
df['Int_div'] = df['X_squared'] // df['X_sqrt'] 
   time_end = datetime.now()  
print(f'Total time = {(time_end - time_start).seconds} seconds')

结果如下:

图 4:Pandas 速度测试——越低越好

需要注意的是这里没有安装本机 Pandas,但 M1 芯片上的 Pandas 以快了 2 倍的速度完成了该基准测试。

性能测试——Scikit-Learn

与 Pandas 一样,这里也没有在本机上安装 Scikit-Learn,只有通过 Rosseta 2 仿真器运行的 Intel MBP 和 M1 MBP 的比较结果。

以下是在该基准测试中执行的任务列表:

  • 从网络上获取数据集;

  • 执行训练 / 测试 split;

  • 声明一个决策树模型并找到最佳参数(2400 个组合 + 5 倍交叉验证);

  • 使用最佳参数拟合模型。


这是一个大致的标准模型训练程序,但不包含测试多种算法,数据准备和特征工程。以下是测试的代码段:

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import accuracy_score, confusion_matrix
time_start = datetime.now()
# Dataset
iris = pd.read_csv('https://gist.githubusercontent.com/curran/a08a1080b88344b0c8a7/raw/0e7a9b0a5d22642a06d3d5b9bcbad9890c8ee534/iris.csv')
time_load = datetime.now()
print(f'Dataset loaded, runtime = {(time_load - time_start).seconds} seconds')
# Train/Test split
X = iris.drop('species', axis=1)
y = iris['species']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
time_split = datetime.now()
print(f'Train/test split, runtime = {(time_split - time_start).seconds} seconds')
# Hyperparameter tuning
model = DecisionTreeClassifier()
params = {'
criterion': ['gini', 'entropy'],
'splitter': ['best', 'random'],
'max_depth': [1, 5, 10, 50, 100, 250, 500, 1000],
'min_samples_split': [2, 5, 10, 15, 20],
'min_samples_leaf': [1, 2, 3, 4, 5],
'max_features': ['auto', 'sqrt', 'log2']
}
clf = GridSearchCV(
estimator=model,
param_grid=params,
cv=5
)
clf.fit(X_train, y_train)
time_optim = datetime.now()
print(f'Hyperparameter optimization, runtime = {(time_optim - time_start).seconds} seconds')
best_model = DecisionTreeClassifier(**clf.best_params_)
best_model.fit(X_train, y_train)
time_end = datetime.now()
print()
print(f'TOTAL RUNTIME = {(time_end - time_start).seconds} seconds')

结果如下:

图 5:Scikit-Learn 速度测试——越低越好。

结果传达了和使用 Pandas 测试时相同的信息——2019 Intel i5 处理器用两倍时长才完成了相同的任务。

新的 M1 芯片绝对是物有所值的,但最好的版本还在后面,毕竟这只是第一代。

原文链接:https://towardsdatascience.com/are-the-new-m1-macbooks-any-good-for-data-science-lets-find-out-e61a01e8cad1

入门苹果M1
相关数据
基准技术

一种简单的模型或启发法,用作比较模型效果时的参考点。基准有助于模型开发者针对特定问题量化最低预期效果。

参数技术

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

数据科学技术

数据科学,又称资料科学,是一门利用数据学习知识的学科,其目标是通过从数据中提取出有价值的部分来生产数据产品。它结合了诸多领域中的理论和技术,包括应用数学、统计、模式识别、机器学习、数据可视化、数据仓库以及高性能计算。数据科学通过运用各种相关的数据来帮助非专业人士理解问题。

超参数技术

在机器学习中,超参数是在学习过程开始之前设置其值的参数。 相反,其他参数的值是通过训练得出的。 不同的模型训练算法需要不同的超参数,一些简单的算法(如普通最小二乘回归)不需要。 给定这些超参数,训练算法从数据中学习参数。相同种类的机器学习模型可能需要不同的超参数来适应不同的数据模式,并且必须对其进行调整以便模型能够最优地解决机器学习问题。 在实际应用中一般需要对超参数进行优化,以找到一个超参数元组(tuple),由这些超参数元组形成一个最优化模型,该模型可以将在给定的独立数据上预定义的损失函数最小化。

奇异值分解技术

类似于特征分解将矩阵分解成特征向量和特征值,奇异值分解(singular value decomposition, SVD)将矩阵分解为奇异向量(singular vector)和奇异值(singular value)。通过分解矩阵,我们可以发现矩阵表示成数组元素时不明显的函数性质。而相比较特征分解,奇异值分解有着更为广泛的应用,这是因为每个实数矩阵都有一个奇异值分解,但未必都有特征分解。例如,非方阵型矩阵没有特征分解,这时只能使用奇异值分解。

TensorFlow技术

TensorFlow是一个开源软件库,用于各种感知和语言理解任务的机器学习。目前被50个团队用于研究和生产许多Google商业产品,如语音识别、Gmail、Google 相册和搜索,其中许多产品曾使用过其前任软件DistBelief。

特征分解技术

线性代数中,特征分解(Eigendecomposition),又称谱分解(Spectral decomposition)是将矩阵分解为由其特征值和特征向量表示的矩阵之积的方法。需要注意只有对可对角化矩阵才可以施以特征分解。

特征工程技术

特征工程是利用数据所在领域的相关知识来构建特征,使得机器学习算法发挥其最佳的过程。它是机器学习中的一个基本应用,实现难度大且代价高。采用自动特征工程方法可以省去采用人工特征工程的需求。Andrew Ng 说“挖掘特征是困难、费时且需要专业知识的事,应用机器学习其实基本上是在做特征工程。”

交叉验证技术

交叉验证,有时亦称循环估计, 是一种统计学上将数据样本切割成较小子集的实用方法。于是可以先在一个子集上做分析, 而其它子集则用来做后续对此分析的确认及验证。 一开始的子集被称为训练集。而其它的子集则被称为验证集或测试集。交叉验证的目标是定义一个数据集到“测试”的模型在训练阶段,以便减少像过拟合的问题,得到该模型将如何衍生到一个独立的数据集的提示。

暂无评论
暂无评论~