dtype データ型
dtype データ型
1. 学習内容
- dtypeシステムと分類
- 特定のデータ型を持つ配列の作成
- 型変換とオーバーフローのリスク
- 構造化データ型
- dtypeにおけるメモリ・精度・速度のトレードオフ
2. ストーリー
アリスのモデルの精度は、一夜にして95%から12%へと低下した。原因は、float64をint8に変換した際に、127を超えるすべての値がオーバーフローして負の数になってしまったことだった。「データ型は些細な問題ではない――間違った型を選んでしまえば、データは台無しになってしまう。」
3. 主要な概念
(1) dtype システム
NumPyのdtype(データ型)は、配列内の各要素の型を表します。すべてのndarrayには.dtype属性があります。
np.int32 # 32-bit signed integer
np.float64 # 64-bit floating point
np.bool_ # boolean
np.str_ # unicode string
np.object_ # Python object
dtype には 2 つのフィールドがあります:
| 項目 | 意味 | 例 |
|---|---|---|
kind |
型カテゴリ | 'i'=int, 'f'=float, 'u'=uint, 'b'=bool |
itemsize |
要素あたりのバイト数 | 4(int32用) |
import numpy as np
a = np.array([1, 2, 3])
print(a.dtype) # int64 (on 64-bit platforms)
print(a.dtype.kind) # 'i'
print(a.dtype.itemsize) # 8
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
(2) 整数型の比較
| タイプ | 範囲 | バイト数 | 別名 |
|---|---|---|---|
int8 |
-128 ~ 127 | 1 | — |
int16 |
-32768 ~ 32767 | 2 | — |
int32 |
-2147483648 ~ 2147483647 | 4 | intp (32ビット) |
int64 |
-9223372036854775808 ~ 9223372036854775807 | 8 | intp (64ビット) |
uint8 |
0 ~ 255 | 1 | — |
uint16 |
0 ~ 65535 | 2 | — |
uint32 |
0 ~ 4294967295 | 4 | — |
uint64 |
0 ~ 18446744073709551615 | 8 | — |
(3) フロート型の比較
| 型 | バイト数 | 精度 | 最大値 | 正の最小値 |
|---|---|---|---|---|
float16 |
2 | 約3桁 | 65504 | 5.96e-8 |
float32 |
4 | 約7桁 | 3.4e38 | 1.18e-38 |
float64 |
8 | 約15桁 | 1.8e308 | 2.23e-308 |
float128 |
16 | 約33桁 | 1.19e4932 | 3.36e-4932 |
float128 は、実際には80ビットの拡張精度を128ビットにパディングしたものであり、真の128ビットではありません。
(4) dtype の指定
import numpy as np
# By NumPy type object
a = np.array([1, 2, 3], dtype=np.float32)
# By string
b = np.array([1, 2, 3], dtype='float32')
# By single-character code
c = np.array([1, 2, 3], dtype='f4') # float32: 'f' + 4 bytes
| 文字 | 種類 | 例 |
|---|---|---|
b |
ブール値 | np.dtype('b') |
i |
signed int | np.dtype('i4') = int32 |
u |
unsigned int | np.dtype('u1') = uint8 |
f |
float | np.dtype('f8') = float64 |
c |
複素数 | np.dtype('c16') = complex128 |
S |
バイト列 | np.dtype('S10') = 10文字の文字列 |
U |
ユニコード文字列 | np.dtype('U5') = 5文字のユニコード |
(5) 型変換とオーバーフロー
import numpy as np
# astype returns a new array with the target dtype
a = np.array([1, 2, 3], dtype=np.int32)
b = a.astype(np.float64) # [1. 2. 3.]
# Overflow: values beyond the target range wrap around
c = np.array([100, 200, 300], dtype=np.uint8)
# [100, 200, 44] — 300 - 256 = 44
# Float to int truncates
d = np.array([1.9, 2.5, 3.1])
print(d.astype(np.int32)) # [1 2 3]
出力: ローカルのPython環境でNumPy 2.xを実行して、ndarrayの出力を確認してください。PistonサーバーにはNumPyがプリインストールされていません。ローカルにインストールして(
pip install numpy)、比較してみてください。実際の値は、NumPyのバージョンやランダムシードによって異なる場合があります。
(6) 構造化データ型
型が混在する表形式のデータについては、構造化されたデータ型を使用してください:
import numpy as np
# Define a structured dtype
dt = np.dtype([('name', 'U10'), ('age', 'i4'), ('salary', 'f8')])
# Create array with structured dtype
employees = np.array([
('Alice', 30, 75000.0),
('Bob', 25, 62000.0),
('Charlie', 35, 85000.0)
], dtype=dt)
print(employees['name']) # ['Alice' 'Bob' 'Charlie']
print(employees['salary'].mean()) # 74000.0
出力: ローカルのPython環境でNumPy 2.xを実行して、ndarrayの出力を確認してください。PistonサーバーにはNumPyがプリインストールされていません。ローカルにインストールして(
pip install numpy)、比較してみてください。実際の値は、NumPyのバージョンやランダムシードによって異なる場合があります。
(1) ▶ サンプル
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
: オーバーフローの実演 (難易度 ⭐⭐)
import numpy as np
# int8 range: -128 to 127
vals = np.array([100, 120, 127, 128, 130, 200], dtype=np.int8)
print("int8 values:", vals)
# [100 120 127 -128 -126 -56]
# uint8 range: 0 to 255
vals_u = np.array([200, 255, 256, 300], dtype=np.uint8)
print("uint8 values:", vals_u)
# [200 255 0 44]
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
(2) ▶ サンプル
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
: 構造化データ型 — 従業員レコード (難易度 ⭐⭐)
import numpy as np
dt = np.dtype([('name', 'U10'), ('dept', 'U15'), ('salary', 'f8'), ('years', 'i2')])
data = np.array([
('Alice', 'Engineering', 95000, 5),
('Bob', 'Marketing', 72000, 3),
('Charlie', 'Engineering', 110000, 8),
('Diana', 'Sales', 68000, 2),
], dtype=dt)
# Query by department
eng = data[data['dept'] == 'Engineering']
print("Engineering avg salary:", eng['salary'].mean())
# Sort by salary
sorted_data = np.sort(data, order='salary')
print("Top earner:", sorted_data[-1]['name'], sorted_data[-1]['salary'])
> Output: Run NumPy 2.x in your local Python environment to see the ndarray output. The Piston server does not have NumPy pre-installed — install it locally (`pip install numpy`) and compare. Actual values may vary by NumPy version and random seed.
4. 比較表
(1) 型変換のルール
| ソース ↓ / ターゲット → | int | float | complex | 文字列 |
|---|---|---|---|---|
| int | ✅ | ✅ (安全) | ✅ (安全) | ✅ (10進数) |
| float | ⚠️ 切り捨て | ✅ | ✅ (安全) | ✅ (小数) |
| 複素数 | ⚠️ 画像が失われる | ⚠️ 画像が失われる | ✅ | ✅ (文字列) |
| bool | ✅ (0/1) | ✅ (0.0/1.0) | ✅ | ✅ |
(2) メモリ対精度行列
| データ型 | 100万要素 | float64に対する相対値 | 用途 |
|---|---|---|---|
| float16 | 2 MB | 25% | GPUによる学習、保存 |
| float32 | 4 MB | 50% | ディープラーニング、ほとんどの機械学習 |
| float64 | 8 MB | 100% | 科学計算 |
| int8 | 1 MB | 12.5% | 画像のバイト数、フラグ |
| int32 | 4 MB | 50% | 汎用整数 |
| int64 | 8 MB | 100% | 大きなインデックス、タイムスタンプ |
(3) オーバーフロー時の挙動
| 演算 | int8 | uint8 | float32 |
|---|---|---|---|
| 最大値 + 1 | -128 (ループ) | 0 (ループ) | 無限大 |
| 最小 - 1 | 127 (ラップ) | 255 (ラップ) | -inf |
| 0 / 0 | エラー | エラー | NaN |
5. 原理図
graph TB
A[Python object] --> B{dtype inference}
B -->|int| C[int64]
B -->|float| D[float64]
B -->|mixed| E[upcast to common type]
B -->|explicit| F[user-specified dtype]
C --> G[ndarray with fixed dtype]
D --> G
E --> G
F --> G
G --> H[vectorized operations]
G --> I[memory-efficient storage]
style A fill:#e1f5fe
style G fill:#c8e6c9
style H fill:#fff9c4
style I fill:#fff9c4
(1) ▶ サンプル:dtypeの変換とメモリ使用量(難易度 ⭐⭐)
import numpy as np
# Compare memory usage of different dtypes
arr_int64 = np.ones(1000000, dtype=np.int64)
arr_float32 = np.ones(1000000, dtype=np.float32)
arr_int8 = np.ones(1000000, dtype=np.int8)
print(f"int64: {arr_int64.nbytes / 1e6:.1f} MB")
print(f"float32: {arr_float32.nbytes / 1e6:.1f} MB")
print(f"int8: {arr_int8.nbytes / 1e6:.1f} MB")
# Convert between types
converted = arr_float32.astype(np.int32)
print(f"Converted dtype: {converted.dtype}")
出力:
TEXTint64: 8.0 MB float32: 4.0 MB int8: 1.0 MB 変換後のデータ型: int32
❓ よくある質問
int64、32ビットプラットフォームでは int32 です。NumPy はシステムのアーキテクチャに基づいて選択します。 dtype=np.int32 を指定して明示的に設定することも可能です。int8(127) + 1 = -128。これはバグのよくある原因です。np.seterr(over='warn') を使ってこれを検出してください。floatおよびdoubleに由来する1文字のコードです。object dtype(Pythonオブジェクトへの参照を格納するため、パフォーマンスが低下します)を使用することは可能です。📖 まとめ
- dtype は、すべての ndarray の要素型を定義し、
kind(カテゴリ)およびitemsize(バイト)フィールドを含みます - 整数型:int8/16/32/64、uint8/16/32/64 — オーバーフローが発生しても黙ってラップする
- float型:float16/32/64/128 — バイト数が多いほど、精度が高くなり、メモリ使用量も増える
np.dtype()を使用して dtype を指定します。オブジェクト、文字列、または 1 文字のコードを指定できます。astype()は型間の変換を行います。オーバーフローの場合は折り返し、float から int への変換では切り捨てが行われます。- 構造化データ型(structured dtypes)を使用すると、単一のndarray内で異なる型の表形式データを扱うことができます
📝 練習問題
-
初心者 (難易度 ⭐): int8、int16、int32、int64、float32、float64 の配列を作成し、それぞれに値 1 の要素を 1000 個格納してください。それらの
nbytesを出力し、メモリ使用量の違いについて説明してください。 -
中級(難易度 ⭐⭐):値が [0, 127, 128, 255, 256, -1] となる uint8 配列を作成してください。どの値がオーバーフローするかを観察し、その結果について説明してください。 次に、タイトル (文字列)、著者 (文字列)、出版年 (int16)、価格 (float32) というフィールドを持つ書籍カタログ用の構造化 dtype を作成してください。
-
上級(難易度 ⭐⭐⭐):100万個の乱数からなるfloat64配列をfloat32に変換し、その後再びfloat64に戻します。 元の配列と往復変換後の配列間の平均絶対誤差を計算する。float16についても同様に繰り返す。各型ごとの精度損失を記録する。