0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DINOv3をバックボーン、Mask2Formerをセグメンテーションのヘッドとして利用するための環境構築手順(備忘録)

0
Posted at

はじめに

DINOv3をバックボーン、Mask2Formerをセグメンテーションのヘッド側として利用するための、Linux環境の構築手順を備忘録としてまとめます。

本記事の対象は、Conda環境の作成、PyTorchとCUDA Toolkitの導入、Detectron2とMask2FormerのCUDA拡張のビルド、DINOv3単体の動作確認までです。環境構築後に必要な接続ラッパーは、実装が必要な雛形として末尾に掲載します。

Mask2Formerのヘッド側には、ピクセルデコーダーとTransformerデコーダーなどが含まれます。両モデルの環境を整えた後、DINOv3の特徴をMask2Formerが受け取れる形へ変換するラッパーを実装する、という順序です。

この記事は、以前環境構築した際のメモを元に、なるべく新しい環境で構築するために再整備した自分用の忘備録です。

1. 対象環境と構築の流れ

NVIDIAドライバー、Conda、Gitが導入済みのLinux x86_64環境を前提とします。本文のコマンドはBashで実行します。

項目 本記事の構築例
OS UbuntuなどのLinux x86_64
Python 3.11
PyTorch 2.7.1、CUDA 12.8版
torchvision 0.22.1
CUDA Toolkit 12.8系
GCC/G++ 11
仮想環境 Conda、dino_m2f_pt271
ビルド並列数 MAX_JOBS=1
GPUアーキテクチャ 使用GPUに合わせて指定

DINOv3公式の学習・評価コードはPyTorch 2.7.1以上を要件とし、公式のConda環境例はPython 3.11を使用しています。本記事では、これを踏まえてバージョンを明示します。DINOv3公式README、公式conda.yaml

PyTorch 2.7.1とtorchvision 0.22.1のCUDA 12.8版は、PyTorch公式の過去バージョン一覧に掲載されています。

手元の元メモはPython 3.10・CUDA 12.4・Ada向けの構成でした。本記事では公式資料を参照し、上表の構築例に整理しています。この組み合わせで一連のビルドを実機再検証した記録ではないため、各節の確認コマンドで結果を確かめながら進めてください。

構築は、Conda環境 → コンパイラとToolkit → PyTorch → Detectron2 → Mask2FormerのCUDA拡張 → DINOv3の順に進めます。

GPUの製品名とCompute Capabilityを確認する

NVIDIA RTX 6000 Ada GenerationとNVIDIA RTX PRO 6000 Blackwell Max-Q Workstation Editionは、異なる世代のGPUです。Compute Capabilityは前者が8.9、後者が12.0のため、使用する製品に合わせて TORCH_CUDA_ARCH_LIST を設定します。

GPU Compute Capability 設定値
NVIDIA RTX 6000 Ada Generation 8.9 TORCH_CUDA_ARCH_LIST="8.9"
GeForce RTX 4090 8.9 TORCH_CUDA_ARCH_LIST="8.9"
NVIDIA RTX PRO 6000 Blackwell Max-Q Workstation Edition 12.0 TORCH_CUDA_ARCH_LIST="12.0"

出典:NVIDIA公式Compute Capability一覧

PyTorch 2.7では、CUDA 12.8版の配布物とBlackwell対応が案内されています。元のCUDA 12.4向け設定で、アーキテクチャ指定だけを 12.0 に変更する手順にはしません。PyTorch 2.7リリース説明

2. GPUとConda環境を確認する

まず、NVIDIAドライバーがGPUを認識していることを確認します。

nvidia-smi
conda --version
git --version

nvidia-smi に表示される「CUDA Version」は、ドライバーが対応するCUDAの情報です。これだけでは、後で使う nvcc のバージョンや、PyTorchに組み込まれたCUDAのバージョンは分かりません。それぞれ別に確認します。

新しい環境を作成します。すでに同名の環境を運用している場合は、検証用に別の名前を付けてください。

conda create -n dino_m2f_pt271 python=3.11 pip -y
conda activate dino_m2f_pt271

python --version
python -m pip --version

以下の作業は、この環境を有効にした同じシェルで進めます。

3. CUDA Toolkitとコンパイラを導入する

PyTorchのGPU用パッケージとは別に、拡張モジュールをビルドするためのCUDA Toolkitを用意します。本文ではConda環境内に配置します。

conda install -c conda-forge gcc_linux-64=11 gxx_linux-64=11 -y
conda install -c nvidia cuda-toolkit=12.8 -y

ビルドで使うパスとコンパイラを指定します。

export CUDA_HOME="$CONDA_PREFIX"
export PATH="$CUDA_HOME/bin:$PATH"
export CC="$CONDA_PREFIX/bin/x86_64-conda-linux-gnu-cc"
export CXX="$CONDA_PREFIX/bin/x86_64-conda-linux-gnu-c++"
export CUDAHOSTCXX="$CXX"
export MAX_JOBS=1

"$CC" --version
"$CXX" --version
command -v nvcc
nvcc --version

nvcc がConda環境内のものを指し、12.8系と表示されることを確認します。/usr/local/cuda など別のToolkitを参照している場合は、先にパスを修正します。

MAX_JOBS=1 は、対応するビルド処理の並列数を抑えてホスト側のメモリ消費を減らす設定です。GPUの学習バッチサイズを変更するものではなく、ビルド時間は長くなる場合があります。

これらの export は現在のシェルに対する設定です。別のターミナルやtmuxの別ペインでビルドする場合も、Conda環境と変数の設定を確認してください。

4. PyTorchを導入してGPU計算を確認する

Condaは環境管理とToolkit導入に使用し、PyTorchは公式のCUDA 12.8版wheelを使用します。

python -m pip install torch==2.7.1 torchvision==0.22.1 \
  --index-url https://download.pytorch.org/whl/cu128

この画像処理構成では torchaudio は使用しません。

続いて、GPUの認識と小さな演算を確認します。

python - <<'PY'
import torch
import torchvision

print("torch:", torch.__version__)
print("torchvision:", torchvision.__version__)
print("PyTorch CUDA:", torch.version.cuda)
print("CUDA available:", torch.cuda.is_available())
assert torch.cuda.is_available(), "GPUを利用できません"
print("GPU:", torch.cuda.get_device_name(0))
print("Compute capability:", torch.cuda.get_device_capability(0))

x = torch.randn(256, 256, device="cuda")
y = x @ x
assert torch.isfinite(y).all().item()
torch.cuda.synchronize()
print("GPU calculation: OK")
PY

ここで torch.version.cuda が 12.8、前節の nvcc --version も12.8系であることを確認します。Detectron2公式のトラブルシューティングでも、PyTorchとビルド用CUDAの整合を確認するよう案内されています。Detectron2インストールガイド

使用GPUのアーキテクチャを指定する

以下は、現在のCUDAデバイス0の値を使用する例です。

export TORCH_CUDA_ARCH_LIST="$(python -c 'import torch; a, b = torch.cuda.get_device_capability(0); print(f"{a}.{b}")')"
printf '%s\n' "$TORCH_CUDA_ARCH_LIST"

Adaなら 8.9、対象のBlackwellなら 12.0 となります。複数種類のGPUで使うバイナリを作る場合は、対象GPUを別途指定する必要があります。

通常はGPUとToolkitを検出できる状態でビルドします。FORCE_CUDA=1 を使う場合も、その用途を区別します。この変数は、対応するセットアップスクリプトにCUDAビルドを指示するためのもので、未対応のGPUやCUDAを使えるようにする設定ではありません。

5. Pythonパッケージと依存関係を整える

最初に、後のインストールでPyTorchが意図せず更新されないよう、constraintsファイルを作ります。

mkdir -p "$HOME/work/dino_m2f_setup"
export DINO_M2F_WORK="$HOME/work/dino_m2f_setup"
export PIP_CONSTRAINT="$DINO_M2F_WORK/constraints.txt"

cat > "$PIP_CONSTRAINT" <<'TXT'
torch==2.7.1
torchvision==0.22.1
TXT

python -m pip install setuptools wheel ninja opencv-python pycocotools

依存解決が衝突した場合は、エラーに示された要求を確認します。constraintsを外してPyTorchを更新すると、ビルド済み拡張の再ビルドが必要になる場合があります。

timmとxformersは使用する実装に合わせる

timm を使うか、DINOv3公式リポジトリを使うかは、ラッパーの実装に依存します。この記事のDINOv3単体確認では公式リポジトリを使用します。

xformers も、使用する実装が必要とする場合に、そのPyTorchに適合する版を選んで導入します。PyTorchの依存を変えてしまわないよう、最新版を無条件に追加せず、必要性と対応バージョンを確認します。

6. Detectron2をソースからビルドする

再構築時にソースの版を追えるよう、リポジトリをローカルへ取得します。

cd "$DINO_M2F_WORK"
git clone https://github.com/facebookresearch/detectron2.git
cd detectron2
git rev-parse HEAD

python -m pip install --no-build-isolation -e .

--no-build-isolation は、現在の環境に導入したPyTorchなどをビルドで参照するための指定です。必要なビルド依存は、現在の環境に用意しておく必要があります。

上の git clone は取得時点のソースを使います。完全な再現には、動作確認したコミットとローカル修正の記録が必要です。

インストール後に確認します。

python -m detectron2.utils.collect_env

python - <<'PY'
import detectron2
from detectron2 import _C
print("Detectron2:", detectron2.__file__)
print("Detectron2 extension:", _C.__file__)
PY

importが成功したことと、CUDA演算がすべて正しく動くことは別です。ここではまずC++拡張を読み込める状態を確認します。

7. Mask2FormerとCUDA拡張をビルドする

本体と依存パッケージ

cd "$DINO_M2F_WORK"
git clone https://github.com/facebookresearch/Mask2Former.git
cd Mask2Former
git rev-parse HEAD

cat requirements.txt
python -m pip install -r requirements.txt
python -m pip check

Mask2Former公式リポジトリはアーカイブされています。古い依存バージョンと新しいPyTorchの組み合わせでは、追加の修正が必要になる場合があります。依存エラーやコンパイルエラーを無視して先へ進めず、変更した依存やソースは記録します。Mask2Former公式インストール手順

Multi-Scale Deformable Attention

ピクセルデコーダーで使用するCUDA拡張をビルドします。

cd "$DINO_M2F_WORK/Mask2Former/mask2former/modeling/pixel_decoder/ops"

export MAX_JOBS=1
set -o pipefail
sh make.sh 2>&1 | tee "$DINO_M2F_WORK/ms_deform_attn_build.log"

pipefail を指定すると、tee が成功しても、ビルド側の失敗を終了ステータスに反映できます。エラーが出たら、この段階で止めてログを確認します。

読み込みと付属テストを確認します。

python - <<'PY'
import MultiScaleDeformableAttention as ops
print("MSDeformAttn extension:", ops.__file__)
PY

python test.py

付属テストでエラーが出る場合は、その内容を確認してから進めます。共有ライブラリのimportに成功しただけでは、forward・backwardの確認は完了していません。

最後にプロジェクトのルートへ戻ります。

cd "$DINO_M2F_WORK/Mask2Former"
python -c "import mask2former; print(mask2former.__file__)"

8. DINOv3本体と重みを用意する

以下は、DINOv3公式実装のViT-L/16を使い、モデル単体で特徴を出力できるか確認する例です。後でラッパーに採用するモデルサイズが異なる場合は、モデル名と重みを変更します。

cd "$DINO_M2F_WORK"
git clone https://github.com/facebookresearch/dinov3.git
cd dinov3
git rev-parse HEAD

cat requirements.txt
python -m pip install -r requirements.txt
python -m pip check

ここでも前節の PIP_CONSTRAINT を有効にして、PyTorchの版を維持します。必要パッケージはソースの版に依存するため、エラーが出た場合は要求を照合します。

学習済み重みの取得にはアクセス手続きが必要

DINOv3のコードをGitHubからcloneする操作と、学習済み重みを取得する操作は別です。リポジトリをcloneしただけでは、重みは手に入りません。 主な取得経路は次の2つです。

取得先 必要な手続き 本記事との関係
Meta公式 公式のダウンロード申請からアクセスを申し込み、承認後にメールで取得URLを受け取る 本文の torch.hub.load() に渡す公式チェックポイントを取得する経路
Hugging Face アカウント登録・ログイン後、対象モデルの条件と連絡先共有への同意を行い、アクセス権を得る 使用するライブラリ・重み形式に合わせて読み込む別経路

A. Meta公式から取得する場合(本文の手順)

  1. DINOv3公式READMEのPretrained modelsを開く。
  2. 対象モデルのダウンロードリンクから申請ページへ進み、必要事項と利用条件を確認して申し込む。
  3. 承認後に届くメールから、使用するモデルの重みのURLを確認する。
  4. URLを使ってローカルへダウンロードする。公式READMEではブラウザではなく wget の使用が案内されている。

ここでの手続きは、重みへのアクセス申請です。「Facebookの一般ユーザーアカウントを作ればダウンロードできる」という意味ではありません。公式の取得案内

以下は保存例です。ViT-L/16用のURLを入力し、異なるモデルサイズの重みを混在させないようにします。

mkdir -p "$DINO_M2F_WORK/weights"
export DINO_WEIGHTS="$DINO_M2F_WORK/weights/dinov3_vitl16.pth"
read -r -p "メールに記載されたViT-L/16重みのURL: " DINO_DOWNLOAD_URL
wget -O "$DINO_WEIGHTS" "$DINO_DOWNLOAD_URL"
unset DINO_DOWNLOAD_URL

ダウンロードが正常終了したことを確認してから、後述の読み込みへ進みます。

B. Hugging Faceから取得する場合

Hugging Faceの公式ViT-L/16モデルページでは、モデルへアクセスするためのログインと、連絡先情報の共有への同意が案内されています。アカウントを作成した後、対象モデルのページで条件を確認し、アクセス手続きを完了させます。アカウント登録だけで手続きが完了するわけではありません。

プログラムから取得する際にも、アクセス権を持つアカウントでの認証が必要です。モデルページの「Use this model」などの案内に従って、使用するライブラリを選びます。

Hugging FaceのTransformers向け配布物を、そのまま次の torch.hub.load(..., weights=...) のファイルパスへ置き換えないでください。 Transformers形式を使う場合は、その配布形式に対応した読み込み方法と出力の扱いに変更します。ファイルの拡張子を .pth に変更するだけでは変換できません。

本文の以降の確認コードは、Aで取得した公式実装向けチェックポイントを前提とします。

重みのパスを指定して単体動作を確認する

次の例は、Aの保存先を使用します。別の場所へ保存した場合は DINO_WEIGHTS を実際のファイルの絶対パスへ変更してください。

export DINO_REPO_DIR="$DINO_M2F_WORK/dinov3"
export DINO_WEIGHTS="$DINO_M2F_WORK/weights/dinov3_vitl16.pth"
test -f "$DINO_WEIGHTS"

ファイルの存在を確認したら、DINOv3単体で特徴を出力できるか確認します。

python - <<'PY'
import os
import torch

model = torch.hub.load(
    os.environ["DINO_REPO_DIR"],
    "dinov3_vitl16",
    source="local",
    weights=os.environ["DINO_WEIGHTS"],
).cuda().eval()

# 実画像の精度評価ではなく、出力形状とGPU動作の確認
x = torch.randn(1, 3, 224, 224, device="cuda")
with torch.inference_mode():
    features = model.forward_features(x)

tokens = features["x_norm_patchtokens"]
print("Patch tokens:", tuple(tokens.shape))
assert torch.isfinite(tokens).all().item()
torch.cuda.synchronize()
PY

この確認は、重みの読み込みとDINOv3単体の演算を対象とします。実画像を入力する際には、採用モデルに合う前処理・正規化も必要です。

9. 環境構築の確認項目

ここまでの作業後、次の結果を確認します。

確認対象 確認方法 確認できること
NVIDIAドライバー nvidia-smi GPUが認識されている
PyTorch 第4節のGPU演算 CUDAを利用した基本演算が実行できる
ビルド用Toolkit nvcc --version 意図したToolkitを参照している
Detectron2 _C のimport、collect_env 拡張の読み込みとビルド環境の情報
MSDeformAttn 拡張のimport、付属の test.py 拡張の読み込みとテスト対象の演算
Mask2Former import mask2former モジュールと必要な依存を読み込める
DINOv3 第8節の特徴抽出 重みを読み込み、GPU上でpatch tokenを出力できる
Python依存 python -m pip check パッケージメタデータ上の依存に矛盾がない

これらが通れば、本記事が対象とする各コンポーネントの環境確認は完了です。DINOv3とMask2Formerを接続したモデルの学習・推論は、末尾のラッパー実装後に確認します。

10. トラブルシューティング

undefined symbol: iJIT_NotifyEvent

元のメモには、MKLを下げる対処が記載されていました。PyTorchのissueでも、MKL 2024.1との組み合わせに関する報告があります。PyTorch issue #123097

conda list mkl

該当する旧Conda構成で問題が起きた場合の対処例です。

conda install "mkl<2024.1"

これは症状と依存関係を確認して行う対処です。本文のpip版PyTorch環境に対して、事前に必ず実行するコマンドではありません。

ビルド中の No module named 'torch'

まず、現在のPythonからtorchを読み込めるかを確認します。

command -v python
python -m pip --version
python -c "import torch; print(torch.__version__)"

通常のPythonではimportでき、ビルド時だけ失敗する場合は、隔離されたビルド環境にtorchがない可能性があります。その場合は、現在の環境のビルド依存を確認し、--no-build-isolation を使います。

ninja: build stopped: subcommand failed

この行は、サブコマンドが失敗したことを示す総括メッセージです。この行だけでメモリ不足とは断定できません。

直前のメッセージなど 確認すること
Killed、cc1plus の強制終了 ホストメモリ不足の可能性。OSログと並列数を確認
nv/target: No such file or directory CUDAヘッダー、CCCL、includeパスの不整合
unsupported GNU version nvccとホストコンパイラの組み合わせ
Unsupported gpu architecture Toolkitが対象GPUのアーキテクチャに対応しているか
PyTorch/ATenのC++ APIに関するエラー 古い拡張ソースと新しいPyTorchの互換性

元のメモの MAX_JOBS=1 はメモリ負荷を下げる対策ですが、ヘッダーやAPIの不整合は解消しません。

nv/target が見つからない

conda list cuda
command -v nvcc
nvcc --version

ToolkitとCCCL関連パッケージが整合しているか、別のCUDAのヘッダーを拾っていないかを確認します。本文の12.8構成に対して、元のメモの cuda-cccl=12.4 を追加するような混在は避けます。

no kernel image is available/invalid device function

GPUアーキテクチャ、PyTorchの配布物、拡張をビルドした環境を照合します。

python -m detectron2.utils.collect_env
python -c "import torch; print(torch.cuda.get_device_capability(0)); print(torch.cuda.get_arch_list())"

PyTorchやCUDAの構成を変更した場合は、Detectron2とMSDeformAttnの古いビルド成果物を確認し、対象の拡張を再ビルドします。使っている環境とは別の環境で作られた .so をコピーして再利用しないようにします。

11. 動作した環境を記録する

備忘録として残すには、インストールコマンドに加えて、実際に解決されたパッケージとソースの版を保存します。

mkdir -p "$DINO_M2F_WORK/environment_record"

conda env export > "$DINO_M2F_WORK/environment_record/environment.yml"
conda list --explicit > "$DINO_M2F_WORK/environment_record/conda-explicit.txt"
python -m pip freeze > "$DINO_M2F_WORK/environment_record/requirements-lock.txt"
python -m detectron2.utils.collect_env > "$DINO_M2F_WORK/environment_record/detectron2-env.txt"
nvidia-smi > "$DINO_M2F_WORK/environment_record/nvidia-smi.txt"
nvcc --version > "$DINO_M2F_WORK/environment_record/nvcc-version.txt"

for repo in detectron2 Mask2Former dinov3; do
  git -C "$DINO_M2F_WORK/$repo" rev-parse HEAD \
    > "$DINO_M2F_WORK/environment_record/${repo}-commit.txt"
  git -C "$DINO_M2F_WORK/$repo" diff HEAD \
    > "$DINO_M2F_WORK/environment_record/${repo}-changes.patch"
done

git diff HEAD には未追跡ファイルは含まれません。独自の dinov3_backbone.py、YAML、実行スクリプトは別途Git管理またはバックアップします。取得した重みのファイル名やチェックサムも記録すると、モデルの取り違えを防げます。

上の環境ファイルは記録の材料です。Condaのexplicitファイルだけではpipパッケージや独自ソースを復元できず、pip freeze にローカルパスが含まれる場合もあるため、別マシンへの復元時には内容を確認します。

補足:接続ラッパーの雛形

環境構築後、DINOv3の出力をMask2Formerへ渡すための dinov3_backbone.py を実装します。以下は登録方法を示す雛形です。未実装部分があり、このまま学習・推論に使用するコードではありません。

ファイルの配置先は、Mask2Former/dinov3_backbone.py です。

from detectron2.layers import ShapeSpec
from detectron2.modeling import BACKBONE_REGISTRY, Backbone


@BACKBONE_REGISTRY.register()
class DINOv3Backbone(Backbone):
    def __init__(self, cfg, input_shape):
        super().__init__()
        # 要実装:DINOv3の生成と重みの読み込み
        # 要実装:特徴ピラミッドと各出力のchannels・strideの定義
        # 要実装:凍結方針、入力サイズの制約など
        raise NotImplementedError("使用モデルに合わせてラッパーを実装してください")

    def forward(self, image):
        # 要実装:patch tokenの取得と空間特徴マップへの変換
        # 要実装:res2〜res5などの特徴辞書を返す
        raise NotImplementedError

    def output_shape(self):
        # 要実装:実際の出力に一致するShapeSpecの辞書を返す
        raise NotImplementedError

元の雛形にある self.dino = ... や「特徴が画像状に整形されていると仮定する」部分は、具体的な処理に置き換える必要があります。実装時に合わせる項目は次のとおりです。

項目 実装・確認する内容
モデル DINOv3のモデル名と、対応する学習済み重み
出力特徴 patch tokenの取得、CLS・register tokenとの区別、空間マップへの変換
特徴ピラミッド 出力の解像度・チャネル数と、output_shape() の整合
入力 RGB/BGR、画素値の範囲、正規化、パディング
学習方針 バックボーンの凍結と学習モードの管理

res2〜res5 は特徴の名前です。名前だけを付けても、期待するstrideやチャネル数にはなりません。使用するモデルに合わせて変換処理を実装します。

ラッパー実装後のYAML設定例

ファイル:Mask2Former/configs/dinov3_m2f_instance.yaml

_BASE_: "coco/instance-segmentation/maskformer2_R50_bs16_50ep.yaml"

MODEL:
  BACKBONE:
    NAME: "DINOv3Backbone"
  WEIGHTS: ""
  SEM_SEG_HEAD:
    IN_FEATURES: ["res2", "res3", "res4", "res5"]

この設定は、ラッパーが上記4つの特徴を返す場合の例です。ピクセルデコーダーが参照する特徴と整合させます。MODEL.WEIGHTS は統合モデル側の重み指定であり、この例ではDINOv3の重みをラッパー内で読み込む設計を想定しています。

設定を読み込む順番

以下は、ラッパー実装後に学習・推論コードへ組み込む例です。

from detectron2.config import get_cfg
from detectron2.projects.deeplab import add_deeplab_config
from mask2former import add_maskformer2_config
import dinov3_backbone  # 独自バックボーンを登録する

cfg = get_cfg()
add_deeplab_config(cfg)
add_maskformer2_config(cfg)
# ラッパーが独自設定キーを使う場合は、ここで登録する
cfg.merge_from_file("configs/dinov3_m2f_instance.yaml")

デモ用の DefaultPredictor を動かす段階では、ラッパーに加え、クラス数・前処理・学習済みの統合チェックポイントを設定します。DINOv3の重みだけでは、新しく接続したMask2Formerのヘッドは学習済みにはなりません。

おわりに

環境構築では、PyTorch・CUDA Toolkit・GPUアーキテクチャをそろえ、Detectron2とMSDeformAttnをビルドします。続いて、Mask2FormerのimportとDINOv3単体の特徴抽出を確認します。

接続ラッパーは、この環境の上で実装する部分です。各コンポーネントの動作確認を先に済ませ、パッケージ・コミット・ビルド条件を保存しておくことで、後のモデル接続や再構築時に問題を切り分けやすくなります。

結論からすると、難易度かなり高めです。個人的には、まずはSwin-Bをバックボーンとして使用することをお勧めします。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?