起源

前陣子因為舊筆電的電池續航完全崩盤,再加上零零總總的小問題,加上零零總總的小問題,因緣際會下入手了 Apple Macbook Air M1 筆電。

然而最近在訓練模型 (Tensorflow, PyTorch, XGBoost) 的時候,發現同樣的模型架構在 M1 和 Google Colab 上的運行結果卻天差地遠
(註:同樣的 Tensorflow 模型在 M1 上的結果相較 Google Colab 差上許多,但有趣的是 XGBoost 的情況卻剛好相反)。

本篇文章主要是在記錄問題觀察和解決過程。

問題觀察

猜測 1: Python 套件版本不同

剛開始懷疑是 Python 套件版本不同導致結果出現差異。
在本機端簡單列出套件版本後在 Google Colab 上執行

1
!pip3 install {package}=={version}

但結果卻沒有差很多,顯然套件版本並不是本次問題的主要原因。

猜測 2: CPU 與 GPU 計算結果差異

當時也考慮過可能是 CPU 和 GPU 造成的結果差異。
在 Google Colab 上方選擇 Runtime > Change runtime type > Hardware accelerator 選則 None 選項即可使用 CPU 訓練模型,但結果依然沒有改善。

猜測 3: Seed 沒有固定

另一種可能原因是訓練的亂數種子 (Seed) 並沒有固定,就重新固定了 Seed。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import numpy as np
import tensorflow as tf

# Seed value
seed_value= 42

# 1. Set `PYTHONHASHSEED` environment variable at a fixed value
import os
os.environ['PYTHONHASHSEED'] = str(seed_value)

# 2. Set `python` built-in pseudo-random generator at a fixed value
import random
random.seed(seed_value)

# 3. Set `numpy` pseudo-random generator at a fixed value
np.random.seed(seed_value)

# 4. Set the `tensorflow` pseudo-random generator at a fixed value
tf.random.set_seed(seed_value)

固定亂數種子後再跑一次訓練,但問題依然沒有解決。

猜測 4: Tensorflow 安裝方式

在觀察的過程中也有發現到載入模型後兩機器的模型權重 (model.get_weights())似乎有些差異,聯想到當時是按照 Apple 官網教學 步驟安裝,而官方提供支持 GPU 版本的 Tensorflow 是基於 2.52.6 版本修改的,因此本篇主題即為透過其他管道運行較高版本的 Tensorflow。

解決過程

如果是透過 pip3 install tensorflow 方式安裝,很高機率會出現查無套件的情況

經過多次嘗試後,發現 Docker 會是最有可能解決問題的方法。 雖然 Tensorflow 有提供 Docker 官方 image tensorflow/tensorflow,不過當時安裝完後執行

1
import tensorflow as tf

會出現 illegal hardware instruction 錯誤,這是因為處理器必須支援 AVXAVX2 (Reference),而 M1 處理器並不支援,因此個人最後選用的 Docker image 是 armswdev/tensorflow-arm-neoverse

1
docker pull armswdev/tensorflow-arm-neoverse

安裝完後執行 import tensorflow as tf,運行成功!
且這次載入模型後基本就和在 Google Colab 的結果相差無幾了,問題解決。

額外補充

如果同時要執行 XGBoost 和 Tensorflow,但選擇先載入 Tensorflow 而後 XGBoost

1
2
import tensorflow as tf
import xgboost

系統會跳出錯誤

解決方法是先載入 XGBoost 而後 Tensorflow

1
2
import xgboost
import tensorflow as tf