20210914のTensorFlowに関する記事は4件です。

Introducing TensorFlow Similarity まとめてみた

TWに流れてきたので、学習の一環としてまとめてみました。 ※ 間違いに気づいたらブラッシュアップします。 ソース:Introducing TensorFlow Similarity September 13, 2021 TensorFlow を使って類似性モデルを簡単かつ迅速にトレーニングするために設計された python パッケージ TensorFlow Similarity が提供しているもの 類似性の学習評価や query を直感的かつ簡単に行うために必要なすべてのコンポーネント 特に、埋め込みインデックスと query をネイティブにサポートする 新しい Keras モデルである SimilarityModel() を導入 初期リリースでフォーカスしていること コントラスト学習に基づく類似性モデルを構築するために必要なすべてのコンポーネントを提供すること (such as losses, indexing, batch samplers, metrics, and tutorials) Keras API との連携や、既存の Keras アーキテクチャの利用を容易に TensorFlow Similarity で可能なこと end-to-end training と 評価 を迅速かつ効率的に行う MNIST data のトレーニング index 作成 検索を行う最小限の例は、20行以下のコードで書ける from tensorflow.keras import layers # Embedding output layer with L2 norm from tensorflow_similarity.layers import MetricEmbedding # Specialized metric loss from tensorflow_similarity.losses import MultiSimilarityLoss # Sub classed keras Model with support for indexing from tensorflow_similarity.models import SimilarityModel # Data sampler that pulls datasets directly from tf dataset catalog from tensorflow_similarity.samplers import TFDatasetMultiShotMemorySampler # Nearest neighbor visualizer from tensorflow_similarity.visualization import viz_neigbors_imgs # Data sampler that generates balanced batches from MNIST dataset sampler = TFDatasetMultiShotMemorySampler(dataset_name='mnist', classes_per_batch=10) # Build a Similarity model using standard Keras layers inputs = layers.Input(shape=(28, 28, 1)) x = layers.Rescaling(1/255)(inputs) x = layers.Conv2D(64, 3, activation='relu')(x) x = layers.Flatten()(x) x = layers.Dense(64, activation='relu')(x) outputs = MetricEmbedding(64)(x) # Build a specialized Similarity model model = SimilarityModel(inputs, outputs) # Train Similarity model using contrastive loss model.compile('adam', loss=MultiSimilarityLoss()) model.fit(sampler, epochs=5) # Index 100 embedded MNIST examples to make them searchable sx, sy = sampler.get_slice(0,100) model.index(x=sx, y=sy, data=sx) # Find the top 5 most similar indexed MNIST examples for a given example qx, qy = sampler.get_slice(3713, 1) nns = model.single_lookup(qx[0]) # Visualize the query example and its top 5 neighbors viz_neigbors_imgs(qx[0], qy[0], nns) ↑ このコードでは最適ではないモデルを使用しているが、以下の画像のように、 Nearest Neighbours が明らかに質問された数字に似ているという良好な結果を得ている。 参考情報:k近傍法(k-Nearest Neighbor) 関連するアイテムを検索する機能 例: マルチメディア検索 レコメンダーシステム クラスタリングパイプライン  → これらのシステムの多くは、対照学習を用いて学習された深層学習モデルを搭載している core information systems の重要な役割: 関連するアイテムを迅速に検索できる 実世界での用途例: 似たような服を見つける 現在流れている曲を特定する 行方不明のペットを助ける 対照学習とは 埋め込み空間をモデルに学習させるもの  同じクラスに属する画像は近くに配置される(集められる)  異なるクラスの画像は遠くに配置される(離れていく) データセット全体に適用した場合: 埋め込み間の距離が入力例の類似性を表わすようにアイテムを埋め込み、空間に投影する方法を学習する Contrastive loss(対照損失)とは: Embedding 空間上での2点間の距離をベースに算定される損失 参考情報:【深層距離学習】Siamese NetworkとContrastive Lossを徹底解説 学習の最終段階 類似アイテム間の距離が小さい 相違アイテム間の距離が大きい 例:  Oxford-IIIT Petデータセットで類似性モデルを学習すると、  見た目が似ている犬種が近く、猫と犬がはっきりと分かれている 意味あるクラスターになる モデル トレーニング 検索可能にしたい様々なアイテムの Embedding を含む index を構築 query (処理要求)時 TensorFlow SimilarityはFast Approximate Nearest Neighbor search (ANN)を活用 index から最も近いマッチングアイテムを sub-linear time (劣線形時間) で検索 fast look up (簡易検索? 高速検索?) が活用している事実 埋め込まれた点の間の距離が有効な距離メトリックの関数 (a function of a valid distance metric)である metric embedding space を学習する → これらの distance metrics は the triangle inequality (三角不等式) を満たす。   そのため、近似最近傍探索が可能な空間となり高い検索精度を実現している。 参考情報:深層距離学習(Deep metric learning)を理解する 最近傍探索とは 距離空間 における最も近い点を探す最適化問題の一種 ベクトルで表現されるデータ(点)の中から、query と最も類似している距離が小さいデータ(最近傍点)を探す手法 モデルの特徴抽出を利用するなど他のアプローチもあるが、関連するアイテムを見つけるために正確な最近傍探索を使用する必要があるため、訓練された類似性モデルほど正確ではない場合がある。 厳密な検索を実行するには、検索インデックスのサイズの a quadratic time (2次時間 ?) が必要 になるため、これらの手法のスケーリングを妨げる。 ↑ ここ自信ありません This prevents those methods ??? (。º̩̩́⌓º̩̩̀).゜ ↓ Other approaches, such as using model feature extraction, require the use of an exact nearest neighbor search to find related items and may not be as accurate as a trained similarity model. This prevents those methods scaling as performing an exact search requires a quadratic time in the size of the search index. 対照的に、TensorFlow Similarityに内蔵されているNMSLIB に依存した Approximate Nearest Neighbor indexing system では、何百万ものインデックス化されたアイテムを検索し、上位K個の類似データを瞬時に取り出すことを可能にしている。 参考情報:最近傍探索 精度と検索速度に加えて、類似性モデルの大きな利点 再学習の必要がなく、無制限に新しいクラスを index に追加できる 新しいクラスの代表的なアイテムの Embedding を計算して、index に追加するだけでよい 動的にクラスを追加する機能が有効なケース 識別可能なアイテムの数が事前に不明 常に変化している 非常に大きい問題に取り組む際 例:  ユーザーが過去に好きだった曲に似た、新しくリリースされた音楽を発見できるようにするなど 今後の予定 この強固な基盤の上に、BYOL、SWAV、SimCLR などの半教師あり学習、自己教師あり学習の手法をサポート予定
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TensorFlowでGPUを使えるようにする

画像解析系のモデルはCPUでも動作しますが処理にかなり時間がかかります。以下TensoFlowでGPUを使えるようにするまでの手順です。 環境 Windows10 使えるGPU NVdia Geforceだけのようです。SoCとかはダメみたいですね Cuda Toolkit インストーラーになっているので指示に従って進めるだけです。自分は推奨インストールにしました。 https://developer.nvidia.com/cuda-downloads 関連の依存があるようでVisualStdio C++がなければインストールするよう警告がでることがあります cuDNN こっちは畳み込みネットワークとかMaxPoolingとかDNNを使うために必要らしいです。面倒ですがDLするためにデベロッパー登録する必要があります。 ダウンロードしたzipを展開して適当な場所に配置してください パスは手動で パスはインストーラーが勝手に登録してくれるという情報がありましたが自分の環境ではそういうことはありませんでした Cuda ToolkitとcuDNNのbinフォルダはPathに手動で登録します
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

TensorFlowでGPUを使えるようにする(Windows編)

CPUだと遅すぎ 画像解析系のモデルはCPUでも動作しますが処理にかなり時間がかかります。以下TensoFlowでGPUを使えるようにするまでの手順です。 環境 Windows10での動作確認です。Linuxは別記事でやります Linux用のdockerコンテナがありますがWindowsでは使えないみたいですね https://www.tensorflow.org/install/gpu 使えるGPU 主要なメーカとしてNvdiaとAMDがありますが、今のところNvdia(Tesla/Geforce/Quadro/etc...)だけのようです。 AMDとかSoCとかはダメみたいですね。使えたという記事を見たことないです。 ここのリンクからCudaが使えるものが見れます https://developer.nvidia.com/cuda-gpus Compute Capability Compute Capabilityっていう性能を表す指標があります。 自分のはGeForceGTX750Tiで5.0でした。2014頃のハイエンドですがもうミドルに落ちてますね Tensorflowのインストール 昔のバージョン(<=1.15)ではTensoflow-gpuというGPU用の別パッケージがあったようですが最近のコードではあまりみないですね pip install tensorflow Cudaのインストール GPUを差しただけではダメで、NVdiaのGPUドライバーのCudaをインストールする必要があります Cuda Toolkit インストーラーになっているので指示に従って進めるだけです。自分は推奨インストールにしました。 https://developer.nvidia.com/cuda-downloads 関連の依存があるようでVisualStdio C++がなければインストールするよう警告がでることがあります cuDNN こっちは畳み込みネットワークとかMaxPoolingとかDNNを使うために必要らしいです。面倒ですがDLするためにデベロッパー登録する必要があります。 ダウンロードしたzipを展開して適当な場所に配置してください cuDNNのパスは手動で パスはインストーラーが勝手に登録してくれるという情報がありましたが、自動で設定してくれるのはCUDAのパスだけです。(CUDA_PATHとCUDA_PATH_V[バージョン]) cuDNNは↓のどちらか 1. cuDNNをパスを手動で設定 2. CUDAと同じフォルダにbin,lib,includeの中身をすべてコピー(これがベストかもしれません。) 下のyolov4のでは2の方式でないとコンパイル通りませんでした https://github.com/AlexeyAB/darknet こちらのページでも2の方式です https://rupic.hatenablog.com/entry/2020/03/24/021455 学習済みモデルで試してみました
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ImageDataGeneratorを使ってみた

はじめに 最近、深層学習の実装ではPytorchに浮気している自分ですが、TensorFlowの中のImageDataGeneratorについて改めて勉強したので、その記録です。 使い方がメインなので、モデル構築や学習は行いません。 環境 Anacondaの仮想環境を使用。 python 3.9.5 Tensorflow 2.5.0 使うデータ Kaggle DatasetのIntel Image Classificationを使います。 {'buildings' -> 0, 'forest' -> 1, 'glacier' -> 2, 'mountain' -> 3, 'sea' -> 4, 'street' -> 5 } の対応になっている6クラス分類です。 基本的な使い方 データのディレクトリ構造をとりあえず以下のように設定します。 data/ ├ seg_train/ │   ├ buildings/ │   ├ forest/ │   ├ glacier/ │     省略 ├ seg_test/ │   ├ buildings/ │   ├ forest/ │   ├ glacier/ │     省略 └ seg_pred/    ├ 10004.jpg    ├ 10005.jpg     省略 seg_trainとseg_testはサブディレクトリがクラスごとに分かれていて、その中に画像が seg_predは予測してほしい画像なので、クラス関係なくごっちゃになって画像がディレクトリ直下に配置されています。 from tensorflow.keras.preprocessing.image import ImageDataGenerator train_dir = './data/seg_train' valid_dir = './data/seg_test' test_dir = './data/seg_pred' train_datagen = ImageDataGenerator(rescale=1./255, # 255で割ることで正規化 zoom_range=0.2, # ランダムにズーム horizontal_flip=True, # 水平反転 rotation_range=40, # ランダムに回転 vertical_flip=True) # 垂直反転 valid_datagen = ImageDataGenerator(rescale=1./255) test_datagen = ImageDataGenerator(rescale=1./255) Generatorをそれぞれtrain用、valid用、test用と用意します。trainは水増しを行い、valid,testは水増しはせず正規化だけします。 ImageDataGeneratorで行える水増し処理一覧は公式ドキュメント参照。 train_generator = train_datagen.flow_from_directory( train_dir, target_size=(64, 64), batch_size=64, class_mode='categorical', shuffle=True) valid_generator = valid_datagen.flow_from_directory( valid_dir, target_size=(64, 64), batch_size=64, class_mode='categorical', shuffle=True) generatorに対して、flow_from_directoryを使用して、画像データを読み取らせます。 この時、上記のように読み取らせたいディレクトリの中にクラスごとに分かれたディレクトリが存在していないとうまく読み取ってくれないので注意。 target_sizeに指定した大きさにリサイズします。 class_modeは今回多クラス分類なのでcategoricalを指定。 うまくいけばこのような表示がされるはず。 Found 14037 images belonging to 6 classes. Found 3000 images belonging to 6 classes. 上がtrainデータ、下がvalidデータについての実行結果です。画像枚数とクラス数が認識できています。 じゃあtestデータに対してもやってみましょう。 # 指定したディレクトリ直下に直接画像があるので認識してくれない test_generator = test_datagen.flow_from_directory( test_dir, target_size=(64,64), batch_size=64, class_mode=None, shuffle=False) 予測データのため、classは何クラスあるかわからないので、class_modeはNoneにします。 ただ、これを実行すると以下のような表示が。 Found 0 images belonging to 1 classes. 先ほども言ったようにtest_dirにはディレクトリ直下にフォルダがなく直接画像データがたくさん置かれています。flow_from_directoryは指定したディレクトリにあるフォルダの数をクラス数として認識するので、フォルダが1つもない場合、画像を正しく読み取ってくれません。 なので何か適当なフォルダを作成して、そこに画像を全部入れてあげればいいです。 # seg_pred/predというディレクトリを作成してその中に画像を格納する # shutilはファイルやディレクトリの移動・削除を扱える import shutil os.makedirs('./data/seg_pred/pred', exist_ok=True) for image_path in glob.glob(test_dir + '/*'): shutil.move(image_path, test_dir + '/pred') seg_predの中にpredというフォルダを作ってそこに画像データを全部移動させています。 shutil.move(移動させたい画像のパス, 移動先のパス)で画像を移動できます。 これでtestデータに対してflow_from_directoryを行えば Found 7301 images belonging to 1 classes. しっかりと7301枚の画像データを認識しています。 ちなみに.class_indicesでどうラベル付けしたか確認できます。 train_generator.class_indices # -> # {'buildings': 0, # 'forest': 1, # 'glacier': 2, # 'mountain': 3, # 'sea': 4, # 'street': 5} どんな画像を生成したのかみてみる 水増しした画像がどういうものか確認することで、意味のない水増しを防げます。 # 1バッチ分取り出す(64個の画像) items = next(iter(train_generator)) plt.figure(figsize=(12,12)) for i, image in enumerate(items[0][:25], 1): plt.subplot(5,5,i) plt.imshow(image) plt.axis('off') ランダムに回転してたり、ちゃんと水増しが適用されていることがわかります。 items[0] が64個の画像データ items[1] が64個のone-hot化されたラベルデータになっています。 なのでラベルも変換して表示できます。 # indexからラベル名に戻すための辞書を定義 index2label_dict = { 0 : 'buildings', 1 : 'forest', 2 : 'glacier', 3 : 'mountain', 4 : 'sea', 5 : 'street'} items = next(iter(train_generator)) plt.figure(figsize=(12,12)) for i, image in enumerate(items[0][:25], 1): label_index = np.argmax(items[1][i-1]) label_name = index2label_dict[label_index] plt.subplot(5,5,i) plt.imshow(image) plt.title(label_name) plt.axis('off') 例えばitems[1][1]の表示は以下のようになっています。 array([0., 0., 1., 0., 0., 0.], dtype=float32) この1になっているのが何番目か知れればラベル名を返せるのでnp.argmaxで取得しています。 ここで水増し画像が訓練データとして適切か確認したらモデル構築・学習へと進む形になります。 まとめ フォルダ構成を整えてあげることが大事だが、そこさえしっかりやれば水増し、前処理までやってくれるので便利だと感じた。 あとはバッチごとにデータを読み込むので、 もっと大量の画像を扱うことになった時にメモリオーバーにならなくていいと思う。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む