- 投稿日:2020-12-15T15:58:52+09:00
CUDA + TensorFlow + Anaconda + Windowsで作る機械学習環境
はじめに
ゲーミング用途などで高性能なGPUを持っている方の中にはそれらを活用して機械学習をやりたいと考える方も多いのではないでしょうか?
しかし、Linuxと比べWindows環境ではGPUを汎用的な計算機として使うためにはそれなりの手間がかかり、実際に機械学習のライブラリであるTensorFlowの公式サイトではLinuxを使ってDockerイメージ(仮想環境)を導入することが推奨されています。
それでも幸いなことにWindows+CUDAを利用している先駆者は多くいるので、充実しつつあるリファレンスをもとに今までよりも手軽にCUDAを導入することができるのではと思います。本稿では、Anacondaで作成したPythonの仮想環境にTensorFlowやその他ライブラリを用意し機械学習を行うことを目標としています。
私の環境
マシンスペック
- OS : Windows10 Pro
- CPU : AMD Ryzen 5 3500
- GPU : Nvidia Geforce GTX 1660 Super
プログラミング環境/使用ツール
- Anaconda
- 仮想環境 - Python3.6.12
- Microsoft Visual Studio 2019 Community
- GPUドライバのバージョン:460.79(自身のGPUに対応するドライバはこちらから確認できます(NVIDIA Driver Downloads))
今回導入したもの
- CUDA Toolkit 10.1
- cuDNN 7.6.5
- TensorFlow 2.3.0
事前準備
GPUドライバのクリーンインストール
- すでに最新版のドライバをいれてる場合でも念の為にクリーンインストールを実行し、プロファイルを初期化するといいと思います。
Visual Studioのインストール
- 拡張機能であるNsight(GPUの状態を解析してくれる)を利用するために必要です。こだわりがなければ最新版のVisual Studio 2019で問題ないと思います。 またTensorFlowを自分でビルドして使いたいという方はこちらの解説記事を参照しC++ビルドツールも一緒にインストールしてください(本稿ではすでにビルド済みのパッケージをインストールすることだけを目的とします)
バージョン対応関係
[!重要!] Python, TensorFlow, CUDA, cuDNN, GPUドライバのバージョン対応関係の確認
CUDAの導入ではこれらのバージョンを自身の環境と合わせ,決められた関係にきっちり対応させる必要があります。
- 基となる対応関係表はこちらを参照してください。Windowsでのテスト済みのビルド構成(GPU)
- 基本的には導入したいTensorFlowとPythonのバージョンを基準とし、そこから上記表を参考にしながらCUDA、cuDNNのバージョンを決めていってください。
- 比較的新しめのGPUだと特に問題ないですが、GPUドライバとCUDAのバージョンも対応させる必要があるのでこちらから確認してください。cuda-toolkit-release-notes
- 私の場合の最終的な導入例は下記の通りです。↓
- TensorFlow=2.3.0 | Python=3.6.12 | cuDNN=7.6.5 | CUDA=10.1
導入の手順
CUDA Toolkitのインストール
CUDA Toolkit Archive
バージョン対応関係にて確認したCUDAのバージョンを上記リンク先から選択しダウンロードし、ダウンロードが終わったらインストールしてください。
無事インストールが完了したらシステム環境変数およびPathの内部にそれぞれ次のようなパスが自動で追加されているはずです。
変数名:「CUDA_PATH」値:「C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1」
変数名:「CUDA_PATH_v10_1」値:「C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1」
Path内部:
「C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\bin」
「C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1\libnvvp」cuDNNのインストール
cuDNN Archive
バージョン対応関係にて確認したcuDNNのバージョンを上記リンク先から選択しダウンロードしてください(Nvidiaアカウントを作成しログインする必要があります)。ダウンロードが終わったらzipを解凍し中身のフォルダを全てCUDAがインストールされているフォルダにコピペし上書きしてください。
そして今度は手動でシステム環境変数にパスを追加します。以下のパスを新規に入力・追加してください。
変数名:「CUDNN_PATH」値 :「C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1」前述したこちらの対応表にある最新のcuDNNのバージョンは7.4ですが、上記のリンク先にあるcuDNNのアーカイブを見るとCUDAのバージョンが10.0までしか対応していません。私は最初一つ上のバージョンである7.5を導入してみましたが、実際に学習を行おうとした際にエラーが出てしまい、試しにv7系で最も最新の7.6.5で行ったところ無事に成功しました。インストールがうまく行ったあとでも学習時にエラーがでるなどしたらcuDNNのバージョンを変更してみてください(フォルダを上書きするだけなので環境に影響はありません)。
3. 再起動する
ここで一旦PCを再起動させておきます。再起動しないとこの後の手順でパスが認識されない可能性があります。4. TensorFlowをインストールする
すでにビルド済みのTensorFlowライブラリをpipでインストールするだけです.過去にtensorflowをインストールした環境であれば先にアンインストールしてください。ライブラリの競合などでエラーがでる可能性もあるのでなるべく新しい仮想環境を作ってからインストールすることをおすすめします。
またバージョン2.1以降は「tensorflow」のみでcpuとgpuを同時にサポートします。それ以前のバージョンをインストールする場合は「tensorflow_gpu」のようにコマンドを入力してください。pip install tensorflow_gputensorflow.v2.1~pip install tensorflow5. 動作確認
まずtensorflowがGPUを利用するために必要なDLLにパスが通っているか確認します。
where cudnn64_7.dllつぎにtensorflowをつかう上で実際にGPUが認識されているか確認します。
python -c "from tensorflow.python.client import device_lib;print(device_lib.list_local_devices());"上記のコードを実行し、各種DLLが正常に読み込まれ「device_type: “GPU”」と表示されれば成功です。(私の場合"XLA_GPU"と表示されましたが問題はなさそうです。なぜそう表示されるのかはわかりませんが…)
CPUと表示されてしまう場合はCUDAやcuDNNの導入に失敗している、またはGPUドライバやそれらのバージョンに間違いがある思われます。おわりに
私の場合、CUDAの導入は大変な苦労と時間をかけてなし得たものでした….
以前に挑戦した際はLinux(Ubuntu)をWindows上の仮想環境(Hyper-V)にインストールした上で導入しようとしましたが、うまくいかずに挫折しました(仮想環境マシンとGPUの接続ができなかったのが原因のようでした)。
その他にもWSLを利用しようとInsider Programを導入したはいいものの、アーリー版ゆえにネットワークにつながらないという致命的なバグに見舞われるなど(PCの)生命の危機を感じたりもして紆余曲折がありました。
最終的には生のWindowsのシステムドライブにCUDAもろもろをインストールしたわけですが、これが一番シンプルでエラーも少ないやり方なのではないかと思います。参考サイト
- NVIDIA公式の導入ガイド CUDA Installation Guide for Microsoft Windows
- Tensorflow公式の導入ガイド TensorFlow 2 をインストールする
- https://www.kkaneko.jp/tools/win/cuda.html
- 投稿日:2020-12-15T11:28:13+09:00
【Python】YouTubeで再生されやすいサムネの特徴をディープラーニングで解析してみた
こんにちは。NTTドコモ入社1年目の九島です。
アドベントカレンダー16日目の本記事では、YouTubeで再生されやすいサムネの特徴をディープラーニングで解析する方法について詳しくご紹介します。
使用したプログラミング言語はPythonです。はじめに
本記事は、以下の2部構成となっています。
- YouTube Data APIをPythonで利用する方法
- ディープラーニングに基づく動画サムネイルの分類
「YouTube Data APIをPythonで利用する方法」では、YouTube動画の情報を取得するために必要な準備から、実際に取得するコードの説明まで記載しています。
本記事を参考にすることで、実際にYouTube動画の視聴回数やサムネイルの画像を取得できます。
「ディープラーニングに基づく動画サムネイルの分類」では、ディープラーニングの一種であるConvolutional Neural Network (CNN)の簡単な説明から、それに基づいて動画サムネイルを分類するコードの説明まで記載しています。
本記事を参考にすることで、実際にCNNで分類モデルを構築し、動画サムネイルに適用できます。
YouTube Data APIを利用してYouTube動画のデータ分析をしたい方や、ディープラーニングでひとまず画像分類をしてみたい方の参考になれば幸いです。
また最終的に、画像分類の結果からどのような画像が多く視聴されるのかを考察しました。
YouTubeで再生されやすいサムネは、以下の特徴がありました。
YouTubeで再生されやすいサムネの特徴
- 色の彩度が高い
- 色の数が多い
- テロップの文字数が多い
- 人物やキャラクターの顔が写っている
※本記事では、Pythonを実行できる環境がある前提で話を進めます。
YouTube Data APIをPythonで利用する方法
YouTube Data APIとは
YouTube Data APIは、YouTubeに投稿されている動画の情報を取得可能なAPIです。
YouTube Data APIの公式ドキュメント:
https://developers.google.com/youtube/v3/getting-started?hl=jaYouTube Data APIで取得可能な動画に関する情報の例を以下に記載します。
- タイトル
- チャンネル名
- 視聴回数
- 高評価数
- サムネイルのURL
本記事では、視聴回数とサムネイルを利用しました。
YouTube Data APIを利用するための準備
YouTube Data APIを利用するためには、以下の準備が必要です。
- Googleアカウントの作成
- 新しいプロジェクトの作成
- APIとサービスの有効化
- APIキーの取得
それぞれの準備について詳細に説明します。
※Googleアカウントの作成は省略します。新しいプロジェクトの作成
以下にアクセスし、「プロジェクトを作成」をクリックして任意の名前の新しいプロジェクトを作成します。
http://console.developers.google.com/projectプロジェクトを作成すると、通知等からプロジェクトの管理画面にアクセスできます。
APIとサービスの有効化
プロジェクトの管理画面にアクセスできたら、「APIの概要に移動」、「APIとサービスの有効化」を順にクリックし、APIライブラリへアクセスします。
APIライブラリでは、有効にしたいAPIを検索することができます。
「YouTube Data API」等で検索し、検索結果の「YouTube Data API v3」を選択、そして「有効にする」をクリックすることで、YouTube Data APIの有効化が完了します。APIキーの取得
プロジェクトの管理画面またはYouTube Data APIの管理画面の左側に「認証情報」というタブがあります。
それをクリックし(プロジェクトの管理画面からクリックした場合はYouTube Data APIを選択後)、「認証情報を作成」、「APIキー」を順にクリックするとAPIキーが作成されます。
※ここで作成したAPIキーは後で使用するのでコピーしておいてください。以上でYouTube Data APIを利用するための準備は完了です。
Python側の準備
PythonでYouTube Data APIを利用するためには、以下のpipコマンドで事前にライブラリをインストールします。
pip install google-api-python-clientYouTube動画の情報を取得
YouTube動画の情報は以下のコードを実行することで取得できます。
from apiclient.discovery import build YOUTUBE_API_KEY = '{取得したAPIキー}' youtube = build('youtube', 'v3', developerKey=YOUTUBE_API_KEY) search_response = youtube.search().list( part='snippet', #検索クエリ q='ゲーム実況', #視聴回数の多い順 order='viewCount', type='video', ).execute()取得した情報の詳細は、以下のように
search_responseの中身を確認することで見ることができます。search_response['items'][0]確認できる要素例:
videoId: 動画のIDchannelId: チャンネルのIDtitle: 動画のタイトルdescription: 動画の説明欄thumbnails: 動画のサムネイル(URL情報)channelTitle: チャンネル名publishTime: 投稿日また、上記の
videoIdを用いて以下のコードを実行することで、動画の視聴回数や高評価数も確認することができます。statistics = youtube.videos().list( #統計情報 part = 'statistics', id = {動画のvideoId} ).execute()['items'][0]['statistics']確認できる要素例:
viewCount: 視聴回数likeCount: 高評価数取得できる情報やAPIの使い方などをより詳細に確認したい方は公式ドキュメントをご覧ください。
YouTube Data APIの公式ドキュメント:
https://developers.google.com/youtube/v3/getting-started?hl=jaまた、複数の動画の情報をデータフレームに格納し、分析したい場合は以下の方法があります。
まず、検索する条件を指定します。
以下のコードでは、検索クエリはゲーム実況、視聴回数の多い順、50件の結果を取得、2020/07/01 - 2020/12/01の期間、など様々なパラメータを用いて検索条件を指定できます。search_response = youtube.search().list( part='snippet', #検索クエリ q='ゲーム実況', #視聴回数の多い順 order='viewCount', type='video', #50件 maxResults=50, #アップロード日が2020/07/01以降 publishedAfter='2020-07-01T00:00:00Z', #アップロード日が2020/12/01以前 publishedBefore='2020-12-01T00:00:00Z' ) output = youtube.search().list( part='snippet', q='ゲーム実況', order='viewCount', type='video', maxResults=50, publishedAfter='2020-07-01T00:00:00Z', publishedBefore='2020-12-01T00:00:00Z' ).execute()次に、for文で検索結果をリストに格納します。
ここで注意していただきたいことは、YouTube Data APIは無料で利用する場合、使用回数に制限があるという点です。
YouTube Data APIの管理画面の左側に「割り当て」というタブがありまして、そちらを確認すると、10,000 Queries / 日という表記があります。
一回のコード実行でどれだけ消費されるか未検証ですが、無料利用の場合は制限があるという点にご注意ください。#ループ回数 num = 20 #動画情報を格納するリスト video_list = [] for i in range(num): video_list = video_list + output['items'] search_response = youtube.search().list_next(search_response, output) output = search_response.execute()最後に、上記で作成したリストをデータフレームへ変換します。
以下では、HighViewCountという変数で視聴回数のフィルタリングをかけています。import pandas as pd #統計情報を取得する関数 def get_statistics(id): statistics = youtube.videos().list(part = 'statistics', id = id).execute()['items'][0]['statistics'] return statistics #フィルタリングする視聴回数の値 HighViewCount = 100000 df = pd.DataFrame(video_list) df1 = pd.DataFrame(list(df['id']))['videoId'] df2 = pd.DataFrame(list(df['snippet']))[['channelTitle','publishedAt','channelId','title','description']] df3 = pd.DataFrame(list(pd.DataFrame(list(pd.DataFrame(list(df['snippet']))['thumbnails']))['high']))['url'] ddf = pd.concat([df1, df2, df3], axis = 1) df_static = pd.DataFrame(list(ddf['videoId'].apply(lambda x : get_statistics(x)))) df_output = pd.concat([ddf,df_static], axis = 1) df_output['viewCount'] = df_output['viewCount'].astype(int) #視聴回数で動画をフィルタリング df_highview = df_output[df_output['viewCount']>=HighViewCount]YouTube動画のサムネイルを取得
前項で取得できたデータフレームを利用して、動画のサムネイルそのものを取得します。
以下、サムネイルを取得するコード例です。
※下に注意点が書いてあります。import requests df_highview = df_highview.drop_duplicates() df_highview = df_highview.reset_index(drop=True) df_loop = df_highview for i in range(len(df_loop)): #URLを入力して画像そのものを取得 response = requests.get(df_loop.loc[i, 'url']) image = response.content filename = './image_' + str(i) + '.jpg' with open(filename, "wb") as f: f.write(image)こちらのコードでは、前項で取得した情報の中のサムネイルURLの部分を取り出し、画像を取得しています。
ただし注意点として、上記のような画像URLへアクセスするコードを書く際には、サーバーへ負担がかからないように工夫してください。
上記のコードは例なので、アクセスする間隔を空けるなどの対処は適宜行なってください。
この点についてより詳細に調べたい方は以下の記事をご参考ください。以上で本記事の一つ目のゴールである「実際にYouTube動画の視聴回数やサムネイルの画像を取得する」が完了しました。
ディープラーニングに基づく動画サムネイルの分類
Convolutional Neural Network (CNN)とは
ディープラーニングの一種であるCNNは、ニューラルネットワークに畳み込み処理を導入した深層学習モデルです。
画像認識・分類に適したモデル構造となっており、その分野でよく使われるモデルです。
本記事では、動画サムネイルに対して一般的な構造のCNNを適用し、分類問題を解きます。分類問題の設定
本記事では、視聴回数とサムネイルの情報を利用することで、視聴回数の多いサムネイルと少ないサムネイルを分類する問題を解くことを考えます。
具体的に、検索クエリをゲーム実況として取得した動画に対して、視聴回数が10万回以上と1万回以下で、正例と負例を分け、それらのサムネイル画像を用いてCNNのモデルを構築します。
※「YouTube動画の情報を取得」の項で登場した変数HighViewCountを変更して検索することで、正例と負例のサムネイルを取得します。動画サムネイルの読み込み
以下のコードでフォルダ上の画像データを読み込みます。
本記事で使用する画像枚数は、正例が749枚、負例が748枚です。import glob import PIL import keras from keras.preprocessing import image #リサイズする画像サイズ input_shape = (256, 256, 3) #クラス数 num_classes = 2 #画像データ x = [] #ラベル(1:正例, 0:負例) y = [] #画像のファイル名 z = [] image_list_positive = glob.glob('{正例の画像フォルダのディレクトリ}/image_?.jpg') for f in image_list_positive: x.append(image.img_to_array(image.load_img(f, target_size=input_shape[:2]))) y.append(1) z.append(f) image_list_negative = glob.glob('{負例の画像フォルダのディレクトリ}/image_?.jpg') for f in image_list_negative: x.append(image.img_to_array(image.load_img(f, target_size=input_shape[:2]))) y.append(0) z.append(f)画像の前処理
以下のコードで画像に対して前処理を適用します。
import numpy as np from keras.utils import plot_model, to_categorical from sklearn.model_selection import train_test_split x = np.asarray(x) x /= 255 y = np.asarray(y) #ラベルをカテゴリカル変数へ変換 y = keras.utils.to_categorical(y, num_classes) #画像データセットを学習用とテスト用に分割 x_train, x_test, y_train, y_test, z_train, z_test = train_test_split(x, y, z, test_size=0.33, random_state= 3) #学習用データセットをモデルの学習でそのまま使用する用と検証用に分割 x_train_train, x_train_val, y_train_train, y_train_val, z_train_train, z_train_val = train_test_split(x_train, y_train, z_train, test_size=0.1, random_state = 3)上記のように分割したデータセットのそれぞれのボリュームを以下に記載します。
len(x_train), len(x_test) 1002, 495 len(x_train_train), len(x_train_val) 901, 101モデルの構築
以下のコードでモデルの構築を行います。
from keras.models import Sequential from keras.layers import Conv2D from keras.layers import MaxPool2D from keras.optimizers import Adam from keras.layers import Dense, Activation, Dropout, Flatten model = Sequential() model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape)) model.add(Conv2D(64, (3, 3), activation='relu')) model.add(MaxPool2D(pool_size=(2, 2))) model.add(Dropout(0.25)) model.add(Flatten()) model.add(Dense(128, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(num_classes, activation='softmax')) adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08) model.compile(loss=keras.losses.categorical_crossentropy, optimizer=adam, metrics=['accuracy'])分類精度の検証
構築したモデルに学習用データを当てはめて学習します。
#バッチサイズ batch_size = 100 #エポック数 epochs = 100 history = model.fit(x_train_train, y_train_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(x_train_val, y_train_val))学習したモデルを用いてテスト用データを分類します。
predictions = model.predict(x_test)分類結果と真値から分類精度を確認します。
- 正解率
Accuracy: 0.76
- 混同行列
True Positive: 178
True Negative: 196
False Positive: 78
False Negative: 43
- 再現率、適合率、F値
Recall: 0.81
Precision: 0.70
F-measure: 0.75本記事では試験的なCNNの適用なので、モデルの構造やバッチサイズ、エポック数をより適切なものに変えることで高精度化が期待できると思います。
また、深層学習なので学習に使用する画像の枚数をもっと増やすべきなのですが、YouTube Data APIを無料版で利用する際の利用制限により、想定よりも画像を集められなかったという背景があります。
YouTube Data APIを利用する方はご注意ください。以上で本記事の二つ目のゴールである「実際にCNNで分類モデルを構築し、動画サムネイルに適用できる」が完了しました。
定性評価
最後に、テスト画像の分類結果からどのような画像が多く視聴されるのかを考察します。
※画像は載せられないので、文章のみになります。正例で正解だった画像及び負例で不正解だった画像(つまり、YouTubeで再生されやすいサムネ)の特徴を以下に挙げます。
YouTubeで再生されやすいサムネの特徴
- 色の彩度が高い
- 色の数が多い
- テロップの文字数が多い
- 人物やキャラクターの顔が写っている
あくまで主観的な評価ですが多少の傾向はあると思いました。
特徴量マップの可視化や、学習する画像の枚数の増加などを行うことで、もう少し明確な特徴が見れると思います。まとめ
本記事では、YouTubeで再生されやすいサムネの特徴をディープラーニングで解析する方法について詳しくご紹介しました。
具体的に、以下の二つのゴールを実現するための方法を記載しました。
- 実際にYouTube動画の視聴回数やサムネイルの画像を取得できる
- 実際にCNNで分類モデルを構築し、動画サムネイルに適用できる
いかがでしたでしょうか?
本記事で少しでもみなさまのお役に立てれば幸いです。YouTube Data APIでは、本記事で使用した情報以外にも多くの情報を取得できます。
今後は他の情報を利用してデータ分析やモデル構築をやってみたいと思います。
また、CNNの構築について、本記事では試験的な適用であったため、今後は適切なモデル構造の模索や最新手法の導入などにチャレンジしたいと思います。参考記事
- 投稿日:2020-12-15T09:41:09+09:00
Tensorflow 2.x+TuringGPUでの環境作成方法
状況
Tensorflow 2.x+TuringGPU環境で、標準のnvidia-containerを利用すると以下のような表示となり、GPUが利用されなかった。
tensorflow/stream_executor/platform/default/dso_loader.cc:44] Successfully opened dynamic library libnvinfer.so.6 tensorflow/stream_executor/platform/default/dso_loader.cc:55] Could not load dynamic library 'libnvinfer_plugin.so.6'; dlerror: libnvinfer_plugin.so.6: cannot open shared object file: No such file or directory tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:30] Cannot dlopen some TensorRT libraries. If you would like to use Nvidia GPU with TensorRT, please make sure the missing libraries mentioned above are installed properly.解決策
tensorflowのコンテナを利用すれば簡単に動作させることができた
docker run -it --gpus all --name containername -itd --shm-size=16g tensorflow/tensorflow:latest-gpu
TensorRTのモジュールの追加インストールをおこなっても解決できなかった。
