Python × AI - 階層クラスタリング(ウォード法)

階層クラスタリングは、これまでの非階層クラスタリングとは違い最も距離が近くて似ている(類似度が高い)組み合わせからまとめていく方法です。

結果として出力される樹形図から、分類の過程でできるクラスタがどのように結合されていくかをひとつずつ確認できるため、最適なクラスタ数を後から決めることができます。

樹形図で視覚的に解釈がしやすいというメリットがある反面、非階層クラスタリングよりも計算量が多くなる傾向があるので結果がでるまでに時間がかかることがあります。

データセットの準備

階層クラスタリング用のデータセットを準備します。

まずscikit-learnのアヤメのデータセットを読み込みます。

解釈がしやすくなるようにサンプル数を10分の1に減らし、4つある説明変数も2つに減らします。(4行目)

選択したデータを最後に散布図に表示します。(10行目)

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

X = load_iris().data[::10, 2:4]
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(1, 1, 1, title="iris")
plt.scatter(X[:, 0], X[:, 1])
for i, element in enumerate(X):
plt.text(element[0] + 0.02, element[1] + 0.02, i)
plt.show()

[実行結果]

散布図に表示されている番号は、樹形図に出てくる番号に対応します。

(樹形図は次回表示します。)

階層クラスタリングの実行

scipyを使って階層クラスタリングを行います。

4行目のmethodには、ウォード法(ward)を設定しています。

ウォード法(ward)は、あるクラスタ同士が結合すると仮定したとき、結合後の全てのクラスタにおいて、クラスタの重心とクラスタ内の各点の距離の2乗和の合計が最小となるようにクラスタを結合させていく方法です。

同じく4行目のmetricには元のデータの点と点の距離の定義で、今回はユークリッド距離(euclidean)を指定しています。

ユークリッド距離とは、2点間の直線距離のことです。

[Google Colaboratory]

1
2
3
4
5
import pandas as pd
from scipy.cluster.hierarchy import linkage

Z = linkage(X, method="ward", metric="euclidean")
pd.DataFrame(Z)

[実行結果]

結果に出力したデータフレームZの意味は次の通りです。

  • 1~2列目
    結合されたクラスタの番号
  • 3列目
    クラスタ間の距離
  • 4列目
    結合後に新しくできたクラスタの中に入っている元のデータの数

次回は、今回の結果を樹形図に表示します。

Python × AI [最適なクラスタ数を探索] - シルエット分析

シルエット分析という方法で、最適なクラスタ数を探索してみます。

シルエット分析では次のような定義で適切なクラスタを推定します。

  • クラスタ内は密になっているほど良い。
  • 各クラスタは遠くに離れているほど良い。

シルエット分析はk-means以外のクラスタリング・アルゴリズムにも適応できます。

シルエット係数

前回のクラスタリング結果に対して、シルエット係数を算出します。

sklearnのライブラリを利用します。

[Google Colaboratory]

1
2
3
4
5
6
7
import numpy as np
from matplotlib import cm
from sklearn.metrics import silhouette_samples

cluster_labels = np.unique(z_km.labels_)
n_clusters = cluster_labels.shape[0]
silhouette_vals = silhouette_samples(X, z_km.labels_)

n_clustersはラベルから取得したクラスタ数3を設定しています。(6行目)

silhouette_samplesにデータとラベルをすることで、シルエット係数を取得することができます。(7行目)

シルエット図

シルエット図を作成するコードは以下の通りです。

シルエット図は全てのサンプルを横向き棒グラフに表示したものになります。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
y_ax_lower,y_ax_upper = 0,0
yticks = []

for i,c in enumerate(cluster_labels):
c_silhouette_vals = silhouette_vals[z_km.labels_==c]
print(len(c_silhouette_vals))
c_silhouette_vals.sort()
y_ax_upper += len(c_silhouette_vals)
color = cm.jet(float(i)/n_clusters)
plt.barh(range(y_ax_lower,y_ax_upper),
c_silhouette_vals,
height = 1.0,
edgecolor = "none",
color = color)
yticks.append((y_ax_lower+y_ax_upper)/2.)
y_ax_lower += len(c_silhouette_vals)

silhouette_avg = np.mean(silhouette_vals)
plt.axvline(silhouette_avg,color = "red",linestyle = "--")
plt.ylabel("Cluster")
plt.xlabel("Silhouette Coefficient")
plt.yticks(yticks,cluster_labels + 1)

適切にクラスタリングできていれば、各クラスタのシルエットの厚さが均等に近くなります。

シルエット係数は、-1から1の間の値をとり次のような意味になります。

  • 1に近いほど、そのクラスタは他のクラスタから遠く離れていることを表す。
    ⇒うまくクラスタ分離できている
  • 0に近いほど、隣接するクラスタと接近または隣接するクラスタと重なっていることを表す。
    ⇒クラスタの分離ができていない
  • マイナスの場合は、クラスタ化されたサンプルは誤ったクラスタに所属している可能性あり。
  • シルエットの厚さは、所属するサンプル数を表す。

[実行結果]

上記のシルエット図より、クラスタ数3でうまくクラスタリングができていることが分かります。

クラスタ数を2に変更

クラスタ数を2に変更(1行目)して散布図を描いてみます。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
km = KMeans(n_clusters=2,
n_init=10,
max_iter=300,
random_state=0)
z_km=km.fit(X_norm)

plt.figure(figsize=(10,3))
plt.scatter(x,y, c=z_km.labels_)
plt.scatter(z_km.cluster_centers_[:,0],z_km.cluster_centers_[:,1],s=250, marker="*",c="red")
plt.show

[実行結果]

クラスタの中心点が、いまいちな位置になっていることが分かります。

クラスタ数2のシルエット図

クラスタ数2のシルエット図を表示します。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import numpy as np
from matplotlib import cm
from sklearn.metrics import silhouette_samples

cluster_labels=np.unique(z_km.labels_)
n_clusters=cluster_labels.shape[0]

silhouette_vals=silhouette_samples(X, z_km.labels_,metric="euclidean")

y_ax_lower,y_ax_upper=0,0
yticks=[]

for i,c in enumerate(cluster_labels):
c_silhouette_vals=silhouette_vals[z_km.labels_==c]
print(len(c_silhouette_vals))
c_silhouette_vals.sort()
y_ax_upper +=len(c_silhouette_vals)
color=cm.jet(float(i)/n_clusters)
plt.barh(range(y_ax_lower,y_ax_upper),
c_silhouette_vals,
height=1.0,
edgecolor="none",
color=color
)
yticks.append((y_ax_lower+y_ax_upper)/2.)
y_ax_lower += len(c_silhouette_vals)

silhouette_avg=np.mean(silhouette_vals)
plt.axvline(silhouette_avg,color="red",linestyle="--")
plt.ylabel("Cluster")
plt.xlabel("Silhouette coefficient")
plt.show
plt.yticks(yticks,cluster_labels + 1)

[実行結果]

クラスタ1のシルエットが厚く、シルエット係数の平均値(赤い破線)よりもクラスタ1のほぼすべてのサンプルが下回っており、クラスタリングが上手くいっていないことが分かります。

つまりクラスタ数2よりもクラスタ数3のほうが、最適なクラスタ数だったということが導き出せます。

Python × AI [最適なクラスタ数を探索] - エルボー法

k-means法を使う際の問題点の1つは、クラスタ数を指定しなければならないことです。

今回はエルボー法という方法で最適なクラスタ数を探索していきます。

エルボー法とは

クラスタリングの性能を数値化するには、クラスタ内の残差平方和(SSE)という指標を用います。

エルボー法は、クラスタの数を変えながら残差平方和(SSE)を計算し結果を図表することで適切なクラスタ数を推定する手法です。

サンプルデータの作成と可視化

サンプルデータを作成し、可視化を行います。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from sklearn.datasets import make_blobs
from sklearn import cluster, preprocessing
# サンプルデータの作成
X,y=make_blobs(n_samples=150, # サンプル点の総数
n_features=2, # 説明変数(次元数)の指定
centers=3, # クラスタの個数
cluster_std=0.5, # クラスタ内の標準偏差
shuffle=True, # サンプルをシャッフル
random_state=0) # 乱数生成器の状態
# データを標準化(スケールを合わせるため)
sc=preprocessing.StandardScaler()
X_norm=sc.fit_transform(X)
x=X_norm[:,0]
y=X_norm[:,1]
plt.figure(figsize=(10,3))
plt.scatter(x,y)
plt.show

[実行結果]

3つのグループに分かれたデータを作成することができました。

残差平方和(SSE)を算出

k-meansにてクラスタ数を1から10までのループし残差平方和(SSE)=km.inertia_を算出しリストに格納します。

残差平方和(SSE)が小さいほど歪みのない良いモデル(クラスタリングがうまくいっているモデル)ということになります。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
distortions = []
for i in range(1,11):
km = KMeans(n_clusters=i,
n_init=10,
max_iter=300,
random_state=0)
km.fit(X_norm)
distortions.append(km.inertia_)

plt.plot(range(1,11),distortions,marker="o")
plt.xticks(range(1,11))
plt.xlabel("Number of clusters")
plt.ylabel("Distortion")
plt.show()

[実行結果]

この図がエルボー図と呼ばれます。

クラスタ数3までは、残差平方和(SSE)が減少しクラスタ数4以降はほぼ横ばいとなっています。

エルボー法では、今回のデータにおいてのクラスタ数3のように急激に変化している点を最適なクラスタ数として選択します。

最適なクラスタ数でのクラスタリング

エルボー法で最適クラスタ数と導き出された3を指定して、クラスタリングを行います。

[Google Colaboratory]

1
2
3
4
5
6
7
8
9
km = KMeans(n_clusters=3,
n_init=10,
max_iter=300,
random_state=0)
z_km=km.fit(X_norm)
plt.figure(figsize=(10,3))
plt.scatter(x,y, c=z_km.labels_)
plt.scatter(z_km.cluster_centers_[:,0],z_km.cluster_centers_[:,1],s=250, marker="*",c="red")
plt.show

[実行結果]

きれいに3つのクラスタ(グループ)に分類することができました。

エルボー法を用いることで、数値として根拠を持ったクラスタ数の探索が可能になることが分かりました。

ただ、かなり明確に分かれたデータでないとエルボー図はなだらかな曲線を描き最適なクラスタ数を判定するのが難しいため、万能な手法ではありません。

次回は別の方法でクラスタ数を探索していきます。

Python × AI [クラスタリング] - k-means++

k-meansのパラメータを調整してクラスタリングを実行し、結果がどうかわるかを見てみます。

k-means++

初期パラメータのinitパラメータをrandomからk-means++にしてクラスターの初期位置を変更します。(1行目)

randomの場合は、クラスターセンターがランダムに設置されますが、k-meansの場合は、初期のクラスターセンターを互いに離れた位置に配置します。

k-means++に設定することにより、より効率的で一貫性のある結果が得られるようになります。

クラスタリングを行い、グラフ化を行います。

[Google Colaboratory]

1
2
3
4
5
6
model = KMeans(n_clusters=3, random_state=0, init="k-means++")
cls_data = df_iris.copy()
model.fit(cls_data)
cluster = model.predict(cls_data)
cls_data["cluster"] = cluster
sns.pairplot(cls_data, hue="cluster")

[実行結果]

調整ランド指数(ARI)

クラスタリングした結果の調整ランド指数(ARI)を算出します。

[Google Colaboratory]

1
2
ari = "ARI: {:.2f}".format(adjusted_rand_score(iris.target, cls_data["cluster"]))
print(ari)

[実行結果]

結果は0.73と前回と同じ結果になりました。

結果は改善しませんでしたが、k-means++はランダムより収束が早いという特徴があるため、基本的にk-means++を使うことをお勧めします。

(initパラメータを指定しなければデフォルトでk-means++となります。)

クラスタ数の変更

クラスタ数を3から2に変更してみます。

クラスタリング、グラフ化、調整ランド指数の算出まで一気に実行します。

[Google Colaboratory]

1
2
3
4
5
model = KMeans(n_clusters=2, random_state=0)
cls_data = df_iris.copy()
cls_data["cluster"] = model.fit_predict(cls_data)
sns.pairplot(cls_data, hue="cluster")
print("ARI: {:.2f}".format(adjusted_rand_score(iris.target, cls_data["cluster"])))

[実行結果]

グラフに表示される色の種類から、2つのクラスタ(グループ)にまとめられたことが分かります。

調整ランド指数(ARI)は0.54と下がってしまったので、今回実施したクラスタ数2よりもクラスタ数3の方が精度が高かったことが分かります。

次回は、適切なクラスタ数を探索する方法を試してみます。

Python × AI [クラスタリング] - 調整ランド指数と正解率

前回クラスタリングを行った結果を、調整ランド指数(Adjusted Rand Index)正解率(Accuracy)という代表的な指標で評価してみます。

2つの指標とも最良の場合に1を返し、関係のないクラスタリングの場合0を返します。

調整ランド指数と正解率で評価

調整ランド指数と正解率で評価を行うためのコードは下記の通りです。

調整ランド指数の算出にはadjusted_rand_score関数を使い、正解率の算出にはaccuracy_scoreを使います。

引数としては両関数とも正解データ予測結果のクラスタ番号を渡しています。

[Google Colaboratory]

1
2
3
4
5
6
from sklearn.metrics import accuracy_score
from sklearn.metrics import adjusted_rand_score
ari = "ARI: {:.2f}".format(adjusted_rand_score(iris.target, cls_data["cluster"]))
accuracy = "Accuracy: {:.2f}".format(accuracy_score(iris.target, cls_data["cluster"]))
print(ari)
print(accuracy)

[実行結果]

調整ランド指数(ARI)は、同じクラスタに属すべきデータ同士が正しく同じクラスタに属しているかどうかを表す指標です。

0.73という結果になっており、まあまあの良い結果だと思います。

正解率(Accuracy)は、クラスタラベルと正解データとの完全一致を表す数字です。

0.01という結果はぜんぜん一致しないことを表していますが、これはラベルとクラスタリングでの予測結果であるクラスタ番号が一致していないことが原因であると思われます。

Python × AI [クラスタリング] - k-means法

前回読み込んだアイリスデータを参照しk-means法でクラスタリングを行います。

クラスタ数(グループ数)

k-means法では、クラスタ数(グループ数)を指定する必要があります。

今回のデータではクラスタ数が3種類(’setosa’、’versicolor’、’virginica’)であることがあらかじめわかっているので問題ありませんが、最適なクラス数は分からないことがほとんどであり、実際の運用や評価を実施して決めることになります。

k-means法

k-means法は、各データ間での距離をもとにグループを分けていく手法です。

最初に適当なクラスタ(グループ)に分けて、クラスタの平均を用いてうまくデータが分かれるように調整していきます。

k-meansの実行

k-meansを実行します。

k-meansのモデルを生成する際のパラメータは以下の通りです。(2行目)

  • n_clusters
    クラスタ数。
    ‘setosa’、’versicolor’、’virginica’の3種類に分類するため3を指定。
  • random_state
    乱数シード。
    固定値を指定しないと毎回結果が変わってしまう。
  • init
    クラスタセンター(セントロイド)の初期化方法。
    基本的なk-meansの結果を得るために“random”を指定。

あとはfit関数にデータを渡すだけで、クラスタリングのモデル構築は完了です。(4行目)

[Google Colaboratory]

1
2
3
4
from sklearn.cluster import KMeans
model = KMeans(n_clusters=3, random_state=0, init="random")
cls_data = df_iris.copy()
model.fit(cls_data)

[実行結果]

クラスタの予測結果取得

クラスタの予測結果を取得するソースコードは以下の通りです。

predict関数で予測結果を取得することができます。

[Google Colaboratory]

1
2
cluster = model.predict(cls_data)
print(cluster)

[実行結果]

各データに対して0, 1, 2というようにクラスタリングのクラスタ番号が出力されます。

予測結果をグラフ化

予測した結果をグラフ化します。

[Google Colaboratory]

1
2
cls_data["cluster"] = cluster
sns.pairplot(cls_data, hue="cluster")

[実行結果]

視覚的に3つのクラスタ(グループ)にまとまっていることが分かります。。

クラスタセンターの取得

model.cluster_centers_で、それぞれのクラスタの中心を取得することができます。

[Google Colaboratory]

1
2
3
cluster_center = pd.DataFrame(model.cluster_centers_)
cluster_center.columns = cls_data.columns[:4]
display(cluster_center)

[実行結果]

クラスタセンターのグラフ表示

クラスタセンターをグラフに表示してみます。

“sepal length”と”sepal width”の2変数に関して、データとクラスタセンターを表示します。

[Google Colaboratory]

1
2
3
4
plt.scatter(cls_data["sepal length (cm)"], cls_data["sepal width (cm)"],c=cls_data["cluster"])
plt.xlabel("sepal length (cm)")
plt.ylabel("sepal width (cm)")
plt.scatter(cluster_center["sepal length (cm)"], cluster_center["sepal width (cm)"], marker="*", color="red")

[実行結果]

赤い★マークで表示されているのが、各クラスタを構成しているクラスターセンターの位置になります。

クラスタ番号で集計した説明変数の平均値

クラスタリングの結果を確認します。

クラスタ番号で集計を行い、説明変数の平均を表示します。

[Google Colaboratory]

1
display(cls_data.groupby("cluster").mean().round(2))

[実行結果]

正解データとの比較

正解データと合わせて、答え合わせを行います。

確認しやすいように花の種類を設定して、花の種類で集計して平均を表示します。

[Google Colaboratory]

1
2
3
4
5
cls_data["target"] = iris.target
cls_data.loc[cls_data["target"] == 0, "target"] = "setosa"
cls_data.loc[cls_data["target"] == 1, "target"] = "versicolor"
cls_data.loc[cls_data["target"] == 2, "target"] = "virginica"
display(cls_data.groupby("target").mean().round(2))

[実行結果]

cluster列にはクラスタ番号の0, 1, 2が表示されています。

4つの変数がすべて一致しているsetosaはクラスタ番号2で全て正しくクラスタ化されていることが分かります。

versicolorvirginicaですが、4つの変数が完全に一致しているわけではありませんが、近い数字にはなっているのでそれなりにクラスタ化されているかと思います。

次回は、調整ランド指数正解率を使ってクラスタリングの結果を評価してみます。

Python × AI [クラスタリング] - データ準備編

データをグルーピングするクラスタリングを行いたいと思います。

今回はクラスタリングを行うデータを準備し、次回はk-means法でクラスタリングを行います。

実行環境としてGoogle Colaboratoryを使います。

アイリスデータの読み込み

sklearn.datasetsに用意されているアイリスデータのデータセットを読み込みます。

アイリスとは「あやめ」という花のことで、花びら(Petal)とがくの長さ(Sepal)で種類を分けることができます。

[Google Colaboratory]

1
2
3
4
5
6
7
8
import pandas as pd
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
%matplotlib inline

iris = load_iris()

iris.data.shape

[実行結果]

データの形状は、150個のサンプルデータがあり、サンプルごとに4種類の変数があることが分かります。

アイリスデータの花の種類

アイリスデータの花の種類を確認します。

[Google Colaboratory]

1
print(iris.target_names)

[実行結果]

‘setosa’、’versicolor’、’virginica’という3種類があることが分かりました。

データフレームに格納

データを扱いやすくするために、データフレームに格納します。

iris.dataで4変数のデータを取得し、columnsにiris.feature_nameを代入することで、カラム名に変数を指定しています。

[Google Colaboratory]

1
2
df_iris = pd.DataFrame(iris.data, columns = iris.feature_names)
df_iris.describe()

describe関数を実行すると、平均値・最小値・最大値などデータの全体像を確認することができます。

[実行結果]

データ数は欠損値がなく全て150個で、平均としてはがく(Sepal)の長さが一番広く、花びら(Petal)の幅が一番せまいことなどが分かります。

データの可視化

pairplot関数を使って、各変数のペアごとに散布図を表示します。

[Google Colaboratory]

1
2
3
import seaborn as sns
df_temp = df_iris.copy()
sns.pairplot(df_temp)

[実行結果]

一番確認しやすい傾向としては、petal lengthpetal widthの関係性が右肩上がりになっていることです。

次回は、今回読み込んだデータを参照しk-means法でクラスタリングを行います。

pingコマンド - 相手と相通できるかどうかを確認

pingコマンドとは

pingは通信相手との疎通を確認するためのコマンドです。

通信相手のIPアドレスかドメイン名を指定して実行し、ネットワーク経路に異常がないかどうかを調べることができます。

よく使うオプションは以下の通りです。

オプション内容
-a名前解決を行い、結果にドメイン名を表示
-i TTLエコー要求パケットの有効期限(TTL)を指定
-l サイズエコー要求パケットのサイズをバイト単位で指定
-n 回数コマンドを1回実行したときに送信するエコー要求パケットの回数を指定
-tCtrl+Cを押すまで、エコー要求パケットを続けて送信

ping実行

pingコマンドを実行してみます。

まずは同一セグメント内にあるWindowsパソコンのIPアドレスを指定します。

[コンソール]

1
ping 10.200.241.47

[実行結果]

1
2
3
4
5
6
7
8
9
10
10.200.241.47 に ping を送信しています 32 バイトのデータ:
10.200.241.47 からの応答: バイト数 =32 時間 <1ms TTL=128
10.200.241.47 からの応答: バイト数 =32 時間 <1ms TTL=128
10.200.241.47 からの応答: バイト数 =32 時間 <1ms TTL=128
10.200.241.47 からの応答: バイト数 =32 時間 <1ms TTL=128

10.200.241.47 の ping 統計:
パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
最小 = 0ms、最大 = 0ms、平均 = 0ms

問題なく疎通できました。

TTLと表示されているのはエコー応答パケットのもので、Windowsの場合128が表示されます。


次にルータを1つはさんだ先にあるLinuxサーバのIPアドレスに対してpingコマンドを実行してみます。

[コンソール]

1
ping 172.40.8.46

[実行結果]

1
2
3
4
5
6
7
8
9
10
172.40.8.46 に ping を送信しています 32 バイトのデータ:
172.40.8.46 からの応答: バイト数 =32 時間 =5ms TTL=63
172.40.8.46 からの応答: バイト数 =32 時間 =20ms TTL=63
172.40.8.46 からの応答: バイト数 =32 時間 =7ms TTL=63
172.40.8.46 からの応答: バイト数 =32 時間 <1ms TTL=63

172.40.8.46 の ping 統計:
パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
最小 = 0ms、最大 = 20ms、平均 = 8ms

これも問題なく疎通できました。

macOSやLinuxの場合、TTLは64が表示されるのですが経由したルータの数が引かれて63となっています。

つまり、TTLの数字をみることで通信相手のOSと経由しているルーターの数がわかることになります。


参考までに疎通ができない場合は、下記のような結果が表示されます。

[到達できないケース]

1
2
3
4
5
6
7
8
192.168.0.1 に ping を送信しています 32 バイトのデータ:
192.168.0.26 からの応答: 宛先ホストに到達できません。
192.168.0.26 からの応答: 宛先ホストに到達できません。
192.168.0.26 からの応答: 宛先ホストに到達できません。
192.168.0.26 からの応答: 宛先ホストに到達できません。

192.168.0.1 の ping 統計:
パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、

tracertコマンド - 経路上のルーターを表示

tracertコマンドとは

tracertは、コマンドを実行したパソコンから通信相手までの経路上にあるルーターを一覧表示するコマンドです。

経由するルーターが近い方から順番に表示されるため、相手にパケットが届くまでの経路が分かります。

通信相手にアクセスできない場合に、どのルーターに問題があるのかを調べる際に役立ちます。

ルーター情報

次のようなルーターの情報が表示されます。

  • TTL(有効期限) [1列目]
    TTLはTime To Liveの略で、パケットの有効期限を意味します。
    機器を1つ経由するごとに数字を1つ減らし、0になったらその時点で中継を止めます。
    パケットが永久に放浪する事態を回避するのが目的です。
  • 応答時間 [2~4列目]
    パソコンから各ルーターにICMPのエコー要求パケットを送ってからエコー応答パケットが返ってくるまでの応答時間です。
    応答時間の測定は、各ルーターごと3回ずつ実施されます。
    4秒以内に応答がない場合は、*が表示されます。
  • IPアドレスまたはドメイン名とIPアドレスのセット [5列目]
    4秒以内に応答がない場合は、「要求がタイムアウトしました」と表示されます。

tracert実行

試しにgoogleに対してtracertコマンドを実行してみます。

[コンソール]

1
tracert google.com

[実行結果]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
google.com [2404:6800:4004:813::200e] へのルートをトレースしています
経由するホップ数は最大 30 です:

1 2 ms 2 ms 2 ms 2400:4050:7c0:3a00:826a:efff:fe31:bd72
2 3 ms 3 ms 117 ms 2400:4050:7c0:3a00::fffe
3 * * * 要求がタイムアウトしました。
4 * * * 要求がタイムアウトしました。
5 6 ms 5 ms 5 ms 2001:380:a120:2e::1
6 8 ms 6 ms 6 ms 2001:4860:1:1::21f5
7 5 ms 7 ms 5 ms 2404:6800:8042::1
8 * * * 要求がタイムアウトしました。
9 6 ms 7 ms 7 ms 2001:4860:0:1::14b9
10 5 ms 5 ms 5 ms nrt20s17-in-x0e.1e100.net [2404:6800:4004:813::200e]

トレースを完了しました。

上記の例では問題なくパケットは目的のサーバに届いています。

経路の途中で「要求がタイムアウトしました。」と表示されており、応答のなかったルーターが3台あったことが分かります。

これはICMPを無効にしている機器の可能性がありますが、tracertコマンドではそのような機器が途中にあっても、処理を続けるため最終的には通信相手までの経路が分かります。

よく使うオプション

よく使うオプションは以下の通りです。

オプション内容
-dIPアドレスの名前解決を行わない。
-w ミリ秒タイムアウト時間をミリ秒で指定する。
-h ルータ数経由するルータの数を指定する。

tracertの動作

tracertコマンドが宛先までの経由を調べる仕組みは下記の通りです。

  1. tracertが実行されたらTTLを「1」に設定したエコー要求パケットを送信する。
    TTLを1つずつ増やしながら順にこれを規定回数繰り返すか、宛先からエコー応答パケットが届くまで届ける。
  2. ルーターは届いたパケットのTTLを1つ小さくする。
  3. ルーターはTTLが0のパケットを時間切れのパケットとして送信元に通知する。
  4. ルータによっては、応答しない設定になっていることもある。
  5. ルーターが応答を返さなくても、その後のルータが応答することもある。
  6. 宛先の機器にエコー要求パケットが届いたら、その機器はエコー応答パケットを返す。
  7. 時間超過パケットやエコー応答パケットが届くと、エコー要求パケットを送ってから届くまでにかかった時間とそのパケットの送信元を表示する。

ipconfigコマンド - リゾルバーキャッシュの表示と削除

DNSリゾルバーキャッシュとは

Windowsパソコンでは、IPアドレスFQDNのキャッシュを保持しています。

(FQDNとは、ホスト名とドメイン名を省略しないで表示したものです)

IPアドレスとFQDNのキャッシュとは、Windowsで管理しているIPアドレスとFQDNの対応表のことでDNSリゾルバーキャッシュと呼ばれます。

通信フロー

FQDNで指定された相手と通信する場合、次のようなフローになります。

  1. DNSリゾルバーキャッシュを参照し、FQDNに対応するIPアドレスがあるかどうかを確認する。
  2. 一致するFQDNがあれば、それに対応するIPアドレスを使って通信を開始する。
  3. 一致するFQDNがなければ、DNSサーバに問い合わせを行う。
  4. DNSサーバに問い合わせた名前解決の結果をWindowsシステムの内部に保持し、外部のDNSサーバへの問い合わせをなるべく減らす。

DNSリゾルバーキャッシュの保持時間

DNSリゾルバーキャッシュのデータの保持時間は、初期設定で1日となっています。

この時間を過ぎればキャッシュは破棄されます。

(OSを再起動した場合もキャッシュのデータはクリアされます)

DNSリゾルバーキャッシュの表示

FQDNで指定した相手と通信できない場合、DNSリゾルバーキャッシュのデータが古くなっている可能性があります。

その場合は、DNSリゾルバーキャッシュを表示してキャッシュの内容を確認してみましょう。

[コンソール]

1
ipconfig /displaydns

[実行結果(例)]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Windows IP 構成

gbc6.jp2.as.criteo.com
----------------------------------------
レコード名 . . . . . . . : gbc6.jp2.as.criteo.com
レコードの種類 . . . . . : 1
Time To Live . . . . . .: 14776
データの長さ . . . . . . : 4
セクション . . . . . . . : 回答
A (ホスト) レコード. . . : 116.213.22.169


レコード名 . . . . . . . : gbc6.jp2.as.criteo.com
レコードの種類 . . . . . : 1
Time To Live . . . . . .: 14776
データの長さ . . . . . . : 4
セクション . . . . . . . : 回答
A (ホスト) レコード. . . : 116.213.22.187


レコード名 . . . . . . . : gbc6.jp2.as.criteo.com
レコードの種類 . . . . . : 1
Time To Live . . . . . .: 14776
データの長さ . . . . . . : 4
セクション . . . . . . . : 回答
A (ホスト) レコード. . . : 116.213.22.192


レコード名 . . . . . . . : gbc6.jp2.as.criteo.com
レコードの種類 . . . . . : 1
Time To Live . . . . . .: 14776
データの長さ . . . . . . : 4
セクション . . . . . . . : 回答
A (ホスト) レコード. . . : 116.213.22.190


レコード名 . . . . . . . : gbc6.jp2.as.criteo.com
レコードの種類 . . . . . : 1
Time To Live . . . . . .: 14776
データの長さ . . . . . . : 4
セクション . . . . . . . : 回答
A (ホスト) レコード. . . : 116.213.22.184
(・・・途中略・・・)

DNSリゾルバーキャッシュの削除

IPアドレスとFQDNの対応付けが間違っている場合は、下記のコマンドでDNSリゾルバーキャッシュの削除を行うことができます。

[コンソール]

1
ipconfig /flushdns

[実行結果]

1
2
3
Windows IP 構成

DNS リゾルバー キャッシュは正常にフラッシュされました。

その後、FQDNでアクセスを行うとDNSサーバへの問い合わせが行われ、正しいIPアドレスを取得してキャッシュに保持されます。

これで正しく通信ができるようになるはずです😀