ベクトル演算とは?内積・ノルム・外積の意味と機械学習での使い方をNumPyで解説

ベクトル演算とは、数の並び(ベクトル)どうしを足す・引く・数倍する、内積をとる、長さ(ノルム)を測るといった計算のことです。機械学習では、データ1件を特徴量のベクトルで表し、予測は「重みとの内積」、似ているかどうかは「内積や距離」で計算するため、この数種類の演算がほぼすべての土台になります。

この記事では、ベクトル演算の種類を「式の意味」「図形としての意味」「NumPyでの書き方」の3つで整理し、機械学習のどこで使われるかを実行例で確かめます。コードはPython 3.12とNumPy 2.5.4で実行しました(2026年10月15日確認)。

ベクトル演算とは

ベクトルは、向きと大きさを持つ量です。数学の授業では矢印で描きますが、プログラムの中では[3, 1]のような数の並びとして扱います。たとえば「身長170cm・体重60kg」の人は[170, 60]という2次元のベクトル、28×28ピクセルの白黒画像は784個の数が並んだ784次元のベクトルです。

ベクトル演算はこの数の並びに対する計算で、主な種類は次のとおりです。

演算結果式(2次元の例)NumPy機械学習での主な使いどころ
和・差ベクトル(a1+b1, a2+b2)a + b、a - b重みの更新、差分・誤差の計算
スカラー倍ベクトル(k·a1, k·a2)k * a学習率を掛ける、スケーリング
要素ごとの積(アダマール積)ベクトル(a1·b1, a2·b2)a * bマスク、重み付け、LSTMのゲート
内積(ドット積)数(スカラー)a1·b1 + a2·b2a @ b、np.dot(a, b)線形モデルの予測、類似度、Attention
ノルム(長さ)数√(a1² + a2²)np.linalg.norm(a)距離、正規化、正則化(L1・L2)
外積(クロス積)ベクトル(3次元)—np.cross(a, b)3Dグラフィックス・物理(機械学習ではまれ)
外積(アウター積)行列a_i·b_j を並べた表np.outer(a, b)共分散行列、勾配の計算
行列×ベクトル(線形変換)ベクトル—A @ vニューラルネットの各層、回転・拡大

基本の4つ:和・差・スカラー倍・要素ごとの積

import numpy as np

a = np.array([3, 1])
b = np.array([1, 2])

print("a + b =", a + b)
print("a - b =", a - b)
print("2 * a =", 2 * a)
print("a * b =", a * b)      # 要素ごとの積(アダマール積)
print("a @ b =", a @ b)      # 内積 3*1 + 1*2
print("|a|  =", np.linalg.norm(a))

実行結果:

a + b = [4 3]
a - b = [ 2 -1]
2 * a = [6 2]
a * b = [3 2]
a @ b = 5
|a|  = 3.1622776601683795

和と差は、同じ位置の成分どうしを足したり引いたりします。図形で言えば、和は矢印をつなげた先、差は「bの先からaの先へ向かう矢印」です。スカラー倍は向きを変えずに長さだけを変えます。

注意したいのがa * bです。NumPyでは*は要素ごとの積(アダマール積)で、結果はベクトルです。数学でいう内積は@(またはnp.dot)で、結果は1つの数になります。この2つの取り違えは、機械学習のコードでよくある間違いです。なお、形の違う配列どうしの計算ではNumPyのブロードキャストのルールが働きます。

内積:2つのベクトルが「どれだけ同じ向きか」

内積は対応する成分の積を足し合わせた数で、a·b = |a||b|cosθ(θは2つのベクトルのなす角)という関係があります。向きがそろうほど大きく、直角なら0、逆向きなら負になります。

import numpy as np

a = np.array([1.0, 0.0])
b = np.array([1.0, 1.0])
c = np.array([-1.0, 0.0])

def angle(u, v):
    cos = (u @ v) / (np.linalg.norm(u) * np.linalg.norm(v))
    return cos, np.degrees(np.arccos(cos))

for name, v in [("b", b), ("c", c), ("[0,1]", np.array([0.0, 1.0]))]:
    cos, deg = angle(a, v)
    print(f"a と {name}: 内積={a @ v:5.1f}  cos={cos:6.3f}  角度={deg:5.1f}度")

実行結果:

a と b: 内積=  1.0  cos= 0.707  角度= 45.0度
a と c: 内積= -1.0  cos=-1.000  角度=180.0度
a と [0,1]: 内積=  0.0  cos= 0.000  角度= 90.0度

内積を両方の長さで割ったものがコサイン類似度です。文書や単語、画像の特徴を表すベクトルどうしで「意味が近いか」を測るときの基本になります。類似度の種類と使い分けはデータの類似度計算で詳しく比べています。

ノルムと距離:ベクトルの長さを測る

ノルムはベクトルの「長さ」です。よく使うのは次の3つです。

  • L2ノルム:成分の2乗和の平方根。ふだんの意味の長さ(ユークリッドノルム)
  • L1ノルム:成分の絶対値の和。碁盤の目の道を歩いた距離に相当
  • 最大値ノルム:成分の絶対値の最大値
import numpy as np

x = np.array([3.0, 4.0])
print("L1ノルム:", np.linalg.norm(x, 1))
print("L2ノルム:", np.linalg.norm(x))
print("最大値ノルム:", np.linalg.norm(x, np.inf))
print("単位ベクトル:", x / np.linalg.norm(x))

p = np.array([1.0, 2.0])
q = np.array([4.0, 6.0])
print("ユークリッド距離:", np.linalg.norm(p - q))
print("マンハッタン距離:", np.abs(p - q).sum())

実行結果:

L1ノルム: 7.0
L2ノルム: 5.0
最大値ノルム: 4.0
単位ベクトル: [0.6 0.8]
ユークリッド距離: 5.0
マンハッタン距離: 7.0

2点の距離は「差のベクトルのノルム」です。k近傍法やk-meansは、この距離でデータの近さを判断します。また、ベクトルを自分のL2ノルムで割ると長さ1の単位ベクトルになり、向きだけを比べたいときに使います。回帰の正則化で、重みのL1ノルムを罰則に使うのがLasso、L2ノルムの2乗を使うのがRidgeです(関数の引数はnumpy.linalg.normの公式ドキュメントで確認できます)。

「外積」は2種類ある

日本語の「外積」は、文脈によって別の計算を指します。高校数学や物理で習うクロス積と、機械学習の数式に出てくるアウター積(直積)です。

import numpy as np

a = np.array([1, 0, 0])
b = np.array([0, 1, 0])
print("外積(クロス積)np.cross:", np.cross(a, b))

u = np.array([1, 2])
v = np.array([3, 4, 5])
print("外積(アウター積)np.outer:")
print(np.outer(u, v))

実行結果:

外積(クロス積)np.cross: [0 0 1]
外積(アウター積)np.outer:
[[ 3  4  5]
 [ 6  8 10]]
  • クロス積(np.cross):3次元の2つのベクトルの両方に垂直なベクトルを返します。3Dの法線や回転の計算で使います。
  • アウター積(np.outer):長さmとnのベクトルから、m×nの行列を作ります。データの共分散行列や、ニューラルネットの重みの勾配はこの形で計算されます。

NumPy 2.5の公式ドキュメントでは、numpy.crossの入力は3次元のベクトルでなければならず、それ以外はValueErrorになると書かれています(2026年10月15日確認)。実際にnp.cross([1, 0], [0, 1])を実行すると「Both input arrays must be (arrays of) 3-dimensional vectors」というエラーになりました。古い記事にある「2次元ベクトルどうしの外積」のコードは、3つ目の成分に0を足して[1, 0, 0]のように書き直す必要があります。

ベクトルの変換:行列を掛けると何が起きるか

「ベクトルの変換」は、多くの場合、行列を掛けてベクトルを別のベクトルに移す線形変換のことです。回転・拡大・縮小・射影は、すべて行列とベクトルの積で書けます。

import numpy as np

theta = np.radians(90)
R = np.array([[np.cos(theta), -np.sin(theta)],
              [np.sin(theta),  np.cos(theta)]])
S = np.array([[2, 0],
              [0, 0.5]])
v = np.array([1.0, 1.0])

print("90度回転:", np.round(R @ v, 3))
print("x方向2倍・y方向0.5倍:", S @ v)

実行結果:

90度回転: [-1.  1.]
x方向2倍・y方向0.5倍: [2.  0.5]

ニューラルネットワークの1つの層も、入力ベクトルに重み行列を掛けて(線形変換して)バイアスを足し、活性化関数を通す処理です。行列の積や逆行列、固有値など行列側の計算はNumPyを使った線形代数の記事にまとめています。

機械学習ではどこで使われるか

ここまでの演算が、実際のモデルの中でどう組み合わさるかを小さな例で確認します。

import numpy as np

# 3件のデータ(特徴量2つ)と、学習済みとみなした重み
X = np.array([[1.0, 2.0],
              [2.0, 0.5],
              [0.0, 1.0]])
w = np.array([0.5, -1.0])
b = 0.2

print("予測値(線形モデル):", X @ w + b)
print("ReLU:", np.maximum(0, X @ w + b))

# 文書ベクトル(単語の出現回数)どうしのコサイン類似度
docs = np.array([[2, 1, 0, 0],
                 [1, 1, 0, 0],
                 [0, 0, 3, 1]], dtype=float)
unit = docs / np.linalg.norm(docs, axis=1, keepdims=True)
print("コサイン類似度の行列:")
print(np.round(unit @ unit.T, 3))

実行結果:

予測値(線形モデル): [-1.3  0.7 -0.8]
ReLU: [0.  0.7 0. ]
コサイン類似度の行列:
[[1.    0.949 0.   ]
 [0.949 1.    0.   ]
 [0.    0.    1.   ]]
  • 線形モデルの予測:データ(行列X)と重みベクトルwの積に、バイアスbを足すだけです。線形回帰もロジスティック回帰も、ニューラルネットの1層も、この形が出発点です。
  • 活性化関数:ReLUはnp.maximum(0, x)という要素ごとの演算です。
  • 類似度:各ベクトルを単位ベクトルにしてから行列積をとると、すべての組み合わせのコサイン類似度が一度に求まります。文書1と2は0.949で近く、文書3とはどちらも0(共通する単語がない)です。検索や推薦、TransformerのAttention(クエリとキーの内積)も同じ考え方です。
  • 学習(勾配降下法):重みの更新は「w ← w − 学習率 × 勾配」で、ベクトルの差とスカラー倍の組み合わせです。

テックジムのAIエンジニア養成コース(16章で機械学習とディープラーニングを学ぶコース)でも、回帰・分類やディープラーニングの章で、こうしたベクトル・行列の計算をPythonで書きながらモデルの中身を確かめていきます。

なぜfor文ではなくベクトル演算で書くのか

同じ内積を、Pythonのfor文とNumPyの@で計算して時間を比べてみます(要素数100万、この記事の作成環境での一例です)。

import numpy as np
import time

rng = np.random.default_rng(0)
a = rng.random(1_000_000)
b = rng.random(1_000_000)

t = time.perf_counter()
s = 0.0
for i in range(len(a)):
    s += a[i] * b[i]
t1 = time.perf_counter() - t

t = time.perf_counter()
s2 = a @ b
t2 = time.perf_counter() - t

print(f"forループ: {s:.4f}  {t1:.3f}秒")
print(f"a @ b    : {s2:.4f}  {t2:.5f}秒")

実行結果:

forループ: 250031.5146  0.157秒
a @ b    : 250031.5146  0.00030秒

結果は同じですが、この環境では@のほうが数百倍速く終わりました。NumPyの配列演算は、ループをPythonではなく最適化された内部のコードで実行するためです。機械学習のコードで「ベクトル化して書く」と言われるのはこのためで、GPUを使うPyTorchなどのライブラリも同じ書き方を前提にしています。

まとめ

  • ベクトル演算の中心は、和・差・スカラー倍・内積・ノルムの5つ。外積と行列×ベクトル(線形変換)がこれに続く
  • NumPyでは*が要素ごとの積、@が内積・行列積。取り違えに注意
  • 内積は「向きのそろい具合」、ノルムは「長さ」、差のノルムは「距離」
  • 「外積」はクロス積(3次元のベクトル)とアウター積(行列)の2種類。NumPy 2.5のnp.crossは3次元専用
  • 機械学習の予測・類似度・学習は、これらの演算の組み合わせで書ける

数学の各分野がプログラミングのどこで使われるかはプログラミングに数学は必要?でも整理しています。

よくある質問

Q. ベクトル演算とは何ですか?

ベクトル(数の並び)どうしの和・差、スカラー倍、内積、ノルム(長さ)などの計算のことです。機械学習ではデータを特徴量のベクトルで表すため、予測・類似度・学習のほとんどがこれらの演算の組み合わせで書かれます。

Q. NumPyの * と @ の違いは何ですか?

* は同じ位置の要素どうしを掛ける要素ごとの積(アダマール積)で、結果は同じ形の配列です。@ は内積・行列積で、1次元のベクトルどうしなら結果は1つの数になります。

Q. 内積とコサイン類似度の違いは?

内積はベクトルの長さの影響を受けます。内積を2つのベクトルの長さ(L2ノルム)で割ったものがコサイン類似度で、-1から1の範囲で向きのそろい具合だけを表します。

Q. NumPyで2次元ベクトルの外積(クロス積)が計算できません。

NumPy 2.5のnp.crossは3次元のベクトル専用で、2次元を渡すとValueErrorになります(公式ドキュメント、2026年10月15日確認)。[x, y, 0]のように3つ目の成分を0にして渡してください。

機械学習の基礎の関連記事

機械学習の全体像は機械学習とは?仕組み・種類・できることを簡単に解説|Pythonで動く例つきにまとめています。

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら