ディープラーニング: オートエンコーダの基礎と種類

ディープラーニング: オートエンコーダの基礎と種類

ディープラーニングが私たちの社会に大きな影響を与えようとしていることは明らかです。 Mobibit の創設者兼 CEO である Pramod Chandrayan 氏は最近、codeburst.io にオートエンコーダーの基礎と種類を紹介し、コード例を提供する記事を公開しました。

[[204722]]

前回の記事「ディープラーニングとは何か、なぜなのか?」(https://goo.gl/Ka3YoF) に引き続き、今日はディープラーニングのアーキテクチャの種類を詳しく見ていき、オートエンコーダについて詳しく説明します。

人間の脳がディープラーニングマシンと連携すると、次のようになります。

ディープ ネットワークの謎を解く前に、まずディープラーニングを定義しましょう。私の理解では:

ディープラーニングは、相互に通信する複数の抽象レイヤーがあり、各レイヤーが前のレイヤーと深く接続され、前のレイヤーからの出力に基づいて決定を下す高度な機械学習手法です。

Investopedia ではディープラーニングを次のように定義しています。

ディープラーニングは、人工知能 (AI) の分野における機械学習のサブセットであり、ネットワークのような構造を持ち、非構造化データやラベルなしデータから教師なしで学習することができます。ディープニューラルラーニングまたはディープニューラルネットワークとも呼ばれます。

今日は、教師なし関連ネットワークがどのように機能するかを詳しく見ていきます。

UPN: 教師なし事前学習ネットワーク

この教師なし学習ネットワークはさらに以下のように分類できる。

  • オートエンコーダ
  • ディープビリーフネットワーク(DBN)
  • 生成的敵対ネットワーク (GAN)

オートエンコーダは、入力層、隠し層 (エンコード層)、デコード層の 3 つの層を持つニューラル ネットワークです。ネットワークの目標は、入力を再構築して、その隠れ層がその入力の適切な表現を学習することです。

オートエンコーダ ニューラル ネットワークは、バックプロパゲーションを適用してターゲット値を入力値と等しく設定する、教師なし機械学習アルゴリズムです。オートエンコーダのトレーニングの目的は、入力を出力にコピーすることです。内部的には、入力を特徴付けるために使用されるコードを記述する隠しレイヤーがあります。


オートエンコーダの目的は関数h(x)≈xを学習することです。言い換えれば、出力 x^ が入力 x とほぼ等しくなるように近似恒等関数を学習します。オートエンコーダはニューラル ネットワークのファミリーに属しますが、PCA (主成分分析) とも密接に関連しています。

オートエンコーダに関する重要な事実:

  • これはPCAに似た教師なし機械学習アルゴリズムである。
  • PCAと同じ目的関数を最小化する
  • それはニューラルネットワークです
  • このニューラルネットワークの目標出力は入力である

オートエンコーダは PCA に似ていますが、PCA よりもはるかに柔軟性があります。エンコード処理中、オートエンコーダは線形変換と非線形変換の両方を表すことができますが、PCA は線形変換のみを実行できます。オートエンコーダのネットワーク表現形式により、ディープラーニング ネットワークを構築するためのレイヤーとして使用できます。

オートエンコーダの種類:

  1. ノイズ除去オートエンコーダ
  2. スパースオートエンコーダ
  3. 変分オートエンコーダ (VAE)
  4. 収縮オートエンコーダ (CAE)

A. ノイズ除去オートエンコーダ

これは最も基本的なタイプのオートエンコーダーであり、破損した入力をランダムに部分的に採用して恒等関数リスクを解決し、オートエンコーダーが回復またはノイズ除去を実行する必要があります。

このテクニックを使用すると、入力を適切に表現できます。適切な表現とは、破損した入力から確実に取得でき、対応するノイズのない入力を復元するために使用できる表現です。

ノイズ除去オートエンコーダの背後にある考え方は単純です。隠れ層に、より堅牢な特徴を発見させ、単にアイデンティティを学習することを防ぐため、破損したバージョンから入力を再構築するようにオートエンコーダをトレーニングします。

入力に適用されるノイズの量はパーセンテージで表されます。一般的には 30% または 0.3 が適切ですが、データが非常に少ない場合は、ノイズをさらに追加することを検討してください。

スタック型ノイズ除去オートエンコーダー (SDA):

これは、レイヤー上で教師なし事前トレーニング メカニズムを使用するノイズ除去オートエンコーダーです。レイヤーが事前トレーニングされて、前のレイヤーの入力に対して特徴選択と特徴抽出が実行された後、教師あり微調整フェーズが続きます。 SDA は、多くのノイズ除去オートエンコーダーを融合したものです。最初の k 層がトレーニングされると、下の層に基づいてコードまたは潜在表現を計算できるため、k+1 番目の層をトレーニングできます。

すべてのレイヤーが事前トレーニングされると、ネットワークは微調整と呼ばれる段階に入ります。ここでは、教師あり学習メカニズムを使用して微調整を行い、教師ありタスクの予測誤差を最小限に抑えます。次に、多層パーセプトロンをトレーニングするのと同じ方法で、ネットワーク全体をトレーニングします。この段階では、各オートエンコーダのエンコード部分のみを考慮します。この段階は監督されており、今後はターゲットクラスをトレーニングに使用します。

コード例によるSDAの説明

このセクションは deeplearning.net (ディープラーニングを理解したい人にとって素晴らしいリファレンス) からの抜粋です。ここでは、スタックされたノイズ除去オートエンコーダーが例を使用してわかりやすく説明されています。

スタックされたノイズ除去オートエンコーダーは、2 つの方法で考えることができます。1 つ目はオートエンコーダーのリストとして、2 つ目は多層パーセプトロン (MLP) としてです。事前トレーニング中は、モデルをオートエンコーダーのリストとして扱い、各オートエンコーダーを個別にトレーニングする最初のアプローチを使用しました。 2 番目のトレーニング フェーズでは、2 番目のアプローチを使用します。これら 2 つのアプローチは次の理由で関連しています。

オートエンコーダのシグモイド層と MLP はパラメータを共有します。

MLP の中間層によって計算された潜在表現は、オートエンコーダへの入力として使用されます。

  1. クラスSdA(オブジェクト):  
  2. 「スタック型ノイズ除去オートエンコーダクラス (SdA)」  
  3. スタック型ノイズ除去オートエンコーダモデルは、複数の 
  4. dAの層`i`の隠れ層は、  
  5. 層 `i+1` の dA。最初の層 dA は入力として次の入力を受け取ります。  
  6. SdA であり、最後の dA の隠れ層が出力を表します。  
  7. 事前学習後、SdAは通常のMLPとして扱われることに注意してください。  
  8. dA は重みを初期化するためにのみ使用されます。  
  9. 「」
  10. デフ__init__(  
  11. 自己、  
  12. numpy_rng、  
  13. theano_rng =なし  
  14. n_ins = 784  
  15. 隠しレイヤーのサイズ= [500, 500],  
  16. n_outs = 10  
  17. 破損レベル= [0.1, 0.1]  
  18. ):  
  19. """ このクラスは、可変数のレイヤーをサポートするために作成されています。
  20. :type numpy_rng: numpy.random.RandomState
  21. :param numpy_rng: 初期値を生成するために使用されるnumpy乱数ジェネレータ 
  22. 重み 
  23. :type theano_rng: theano.tensor.shared_randomstreams.RandomStreams  
  24. :param theano_rng: Theano乱数ジェネレータ。Noneが指定された場合は 
  25. `rng` から抽出されたシードに基づいて生成される 
  26. :type n_ins: int
  27. :param n_ins: sdAへの入力の次元 
  28. :type hidden_​​layers_sizes: intのリスト 
  29. :param hidden_​​layers_sizes: 中間層のサイズ。  
  30. 少なくとも1つの値 
  31. :type n_outs: int  
  32. :param n_outs: ネットワークの出力の次元 
  33. :type corruption_levels: float のリスト 
  34. :param corruption_levels: それぞれに使用する破損の量 
  35.  
  36. 「」  
  37. 自己.シグモイドレイヤー= []
  38. 自己.dA_レイヤー= []  
  39. 自己パラメータ= []  
  40. self.n_layers = len (隠しレイヤーのサイズ)  
  41. self.n_layers > 0 をアサートする
  42. そうでない場合 theano_rng:
  43. theano_rng =ランダムストリーム(numpy_rng.randint(2**30))  
  44. # データにシンボリック変数を割り当てる 
  45. self.x = T .matrix('x') # データはラスタライズされた画像として表示されます 
  46. self.y = T .ivector('y') # ラベルは1次元ベクトルとして表されます 
  47. # [int] ラベル

self.sigmoid_layers はシグモイド層を MLP の形式で保存し、self.dA_layers はその MLP 層に関連付けられたノイズ除去オートエンコーダーを保存します。次に、n_layers のシグモイド層と n_layers のノイズ除去オートエンコーダを構築します。ここで、n_layers はモデルの深さです。多層パーセプトロンで導入されたHiddenLayerクラスを使用しますが、1つの変更点があります。tanh非線形性をロジスティック関数に置き換えます。

シグモイド層を連鎖させて MLP を構築し、各オートエンコーダのエンコード部分が対応するシグモイド層と重み行列とバイアスを共有するようにオートエンコーダを構築しました。

  1. i が範囲内(self.n_layers)の場合:  
  2. # シグモイド層を構築する 
  3. # 入力のサイズは隠れユニットの数か 
  4. # 下のレイヤー、または最初のレイヤーの場合は入力サイズ 
  5. i == 0 の場合:  
  6. 入力サイズ= n_ins    
  7. それ以外:  
  8. 入力サイズ=隠しレイヤーのサイズ[i - 1]  
  9. # この層への入力は、隠れ層の活性化か 
  10. # 下のレイヤー、または最初のレイヤーにいる場合はSdAの入力 
  11. # レイヤー 
  12. i == 0 の場合:  
  13. レイヤー入力=自己.x  
  14. それ以外:  
  15. レイヤー入力=自己.シグモイドレイヤー[-1].出力 
  16. sigmoid_layer = HiddenLayer ( rng = numpy_rng  
  17. 入力=レイヤー入力  
  18. n_in =入力サイズ  
  19. n_out =隠しレイヤーのサイズ[i],  
  20. 活性化= T .nnet.sigmoid)  
  21. # レイヤーをレイヤーリストに追加します 
  22. self.sigmoid_layers.append(シグモイドレイヤー)  
  23. # それはおそらく哲学的な質問です...
  24. # ただし、ここでは、
  25. # sigmoid_layersはStackedDAAのパラメータです
  26. # dAの目に見えるバイアスは、それらのパラメータです 
  27. # dA だが SdA ではない 
  28. self.params.extend(シグモイドレイヤー.params)  
  29. # これと重みを共有するノイズ除去オートエンコーダを構築します 
  30. # レイヤー 
  31. dA dA_layer = dA( numpy_rng numpy_rng = numpy_rng,  
  32. theano_rng theano_rng =theano_rng、  
  33. 入力=レイヤー入力  
  34. n_visible =入力サイズ  
  35. n_hidden =隠しレイヤーのサイズ[i],  
  36. W =シグモイド層.W、  
  37. bhid =シグモイド層.b)  
  38. self.dA_layers.append(dA_layer)

ここで、このシグモイド層の上にロジスティック層を追加するだけで、MLP が完成します。 Logistic Regression を使用して MNIST 数字を分類するで紹介された LogisticRegression クラスを使用します。

  1. # MLPの上にロジスティックレイヤーを追加する必要があります 
  2. self.logLayer =ロジスティック回帰(  
  3. 入力=自己.シグモイドレイヤー[-1].出力、
  4. n_in =隠しレイヤーのサイズ[-1],  
  5. n_out = n_outs    
  6. 自己のパラメータを拡張します(自己のログレイヤーのパラメータ)  
  7. # 微調整の1ステップを実装する関数を構築する 
  8. # トレーニングの第2フェーズのコストを計算します。  
  9. # 負の対数尤度として定義される 
  10. 自己self.finetune_cost = self.logLayer.negative_log_likelihood(self.y)
  11. # モデルパラメータに関する勾配を計算する
  12. # エラーの数を示すシンボリック変数 
  13. # self.x と self.y によって与えられたミニバッチ 
  14. 自己self.errors = self.logLayer.errors(self.y)

SdA クラスは、レイヤー内のノイズ除去オートエンコーダのトレーニング関数を生成するメソッドも提供します。これらはリストとして返されます。要素 i は、i 番目のレイヤーに対応する dA をトレーニングするための手順を実装する関数です。

  1. 事前トレーニング関数を定義します(self、train_set_x、batch_size):  
  2. ''' 関数のリストを生成し、それぞれが1つの関数を実装する。  
  3. 同じインデックスを持つレイヤーに対応する dA をトレーニングするステップ。  
  4. この関数はミニバッチインデックスを入力として必要とし、訓練するために 
  5. dAの場合は、対応する関数を呼び出し、反復するだけです。
  6. すべてのミニバッチインデックス。
  7. :type train_set_x: theano.tensor.TensorType  
  8. :param train_set_x: 使用されるすべてのデータポイントを含む共有変数 
  9. dAのトレーニング用 
  10. :type バッチサイズ: int  
  11. :param batch_size: [ミニ]バッチのサイズ
  12. :type 学習率: float  
  13. :param learning_rate: トレーニング中に使用される学習率。  
  14. dA層
  15. '''  
  16. # [ミニ]バッチのインデックス 
  17. index = T .lscalar('index') # ミニバッチのインデックス

トレーニング中に損傷レベルまたは学習率を変更するには、それらを Theano 変数に関連付けます。

  1. corruption_level = T .scalar('corruption') # 使用する破損の割合 
  2. learning_rate = T .scalar('lr') # 使用する学習率 
  3. # `index` を指定してバッチを開始します 
  4. batch_begin =インデックス* batch_size  
  5. # `index` で指定されたバッチの終了 
  6. バッチ終了=バッチ開始+ バッチサイズ 
  7. 事前トレーニングfns = []
  8. self.dA_layers 内の dA の場合:  
  9. # コストと更新リストを取得する 
  10. コスト、更新= dA.get_cost_updates (corruption_level、  
  11. 学習率 
  12. # theano関数をコンパイルする 
  13. fn = theano.function (  
  14. 入力=[  
  15. 索引、  
  16. theano.In(破損レベル、= 0 .2)、  
  17. theano.In(学習率、= 0 .1)  
  18. ]、  
  19. 出力=コスト  
  20. アップデートアップデート=アップデート、  
  21. 与えられたもの= {  
  22. self.x: train_set_x[バッチ開始:バッチ終了]  
  23. }  
  24.  
  25. # 関数のリストに `fn` を追加します 
  26. pretrain_fns.append(fn)  
  27. pretrain_fnsを返す

これで、どの pretrain_fns[i] 関数も、オプションで corruption (破損レベル) または lr (学習率) を含むインデックス パラメータを受け取ることができるようになりました。これらのパラメータ名は、Theano 変数が構築されたときに付けられた名前であり、Python 変数の名前 (learning_rate または corruption_level) ではないことに注意してください。これは、Theano を使用するときに留意しておくべき重要な点です。同様に、微調整時に必要な関数(train_fn、valid_score、test_score)を構築するためのメソッドも構築しました。

  1. def build_finetune_functions(self、データセット、バッチサイズ、学習率):  
  2. '''1ステップを実装する関数`train`を生成します 
  3. 微調整、エラーを計算する関数「validate」  
  4. 検証セットからのバッチと関数「test」  
  5. テストセットからバッチのエラーを計算する 
  6. :type データセット: theano.tensor.TensorType のペアのリスト
  7. :param datasets: すべてのデータセットを含むリストです。  
  8. には3つのペア「train」が含まれている必要があります。  
  9. `valid`、`test` の順で、各ペアは 
  10. 2つのTheano変数で構成され、1つは 
  11. データポイント用とラベル用 
  12. :type バッチサイズ: int  
  13. :param batch_size: ミニバッチのサイズ
  14. :type 学習率: float
  15. :param learning_rate: 微調整段階で使用される学習率 
  16. '''  
  17. (train_set_x, train_set_y) = データセット[0]  
  18. (valid_set_x, valid_set_y) = データセット[1]  
  19. (test_set_x, test_set_y) = データセット[2]  
  20. # トレーニング、検証、テストのミニバッチの数を計算します 
  21. n_valid_batches = valid_set_x .get_value(借用= True ).shape[0]  
  22. n_valid_batches //= バッチサイズ 
  23. n_test_batches = test_set_x .get_value(借用= True ).shape[0]  
  24. n_test_batches //= バッチサイズ 
  25. index = T .lscalar('index') # [ミニ]バッチのインデックス 
  26. # モデルパラメータに関する勾配を計算する 
  27. gparams = T .grad(self.finetune_cost, self.params)  
  28. # 微調整更新のリストを計算する 
  29. アップデート= [  
  30. (param、param - gparam * 学習率)  
  31. param、gparam は zip(self.params, gparams) 内 
  32. ]  
  33. train_fn = theano.function (  
  34. 入力= [インデックス],  
  35. 出力= self.finetune_cost  
  36. アップデートアップデート=アップデート、  
  37. 与えられたもの= {  
  38. 自己.x: トレーニングセットx[
  39. インデックス * バッチサイズ: (インデックス + 1) * バッチサイズ 
  40. ]、  
  41. self.y: トレーニングセットy[  
  42. インデックス * バッチサイズ: (インデックス + 1) * バッチサイズ 
  43. ]  
  44. },  
  45.  
  46. test_score_i = theano .function(  
  47. [索引]、  
  48. 自己エラー、  
  49. 与えられたもの= {  
  50. 自己.x: テストセットx[  
  51. インデックス * バッチサイズ: (インデックス + 1) * バッチサイズ 
  52. ]、  
  53. self.y: テストセットy[  
  54. インデックス * バッチサイズ: (インデックス + 1) * バッチサイズ 
  55. ]  
  56. },  
  57.  
  58. valid_score_i = theano .function(  
  59. [索引]、  
  60. 自己エラー、  
  61. 与えられたもの= {  
  62. 自己.x: 有効なセットx[  
  63. インデックス * バッチサイズ: (インデックス + 1) * バッチサイズ 
  64. ]、  
  65. 自己.y: 有効な_set_y[  
  66. インデックス * バッチサイズ: (インデックス + 1) * バッチサイズ 
  67. ]  
  68. },  
  69.  
  70. # 検証セット全体をスキャンする関数を作成する 
  71. 有効なスコアを定義する():  
  72. [iが範囲内(n_valid_batches)の場合、valid_score_i(i)] を返します。  
  73. # テストセット全体をスキャンする関数を作成する 
  74. テストスコア()を定義します:
  75. [test_score_i(i) を i が範囲内(n_test_batches)] の場合に返す 
  76. train_fn、valid_score、test_scoreを返す

valid_score と test_score は Theano 関数ではなく、それぞれ検証セット全体とテストセット全体をループして、これらのセットの損失のリストを生成する Python 関数であることに注意してください。

要約する

次の数行のコードは、スタックされたノイズ除去オートエンコーダを構築します。

  1. numpy numpy_rng = numpy.random.RandomState(89677)  
  2. print('... モデルを構築しています')  
  3. # スタックされたノイズ除去オートエンコーダクラスを構築する 
  4. sda = SdA (  
  5. numpy_rng numpy_rng = numpy_rng、  
  6. n_ins = 28 * 28、  
  7. 隠しレイヤーのサイズ= [1000, 1000, 1000],  
  8. n_outs = 10    

ネットワークは、レイヤーごとの事前トレーニングとそれに続く微調整の 2 段階でトレーニングされます。

事前トレーニング段階では、ネットワークのすべてのレイヤーをループします。各レイヤーでは、SGD ステップを実装するコンパイル済み関数を使用して重みを最適化し、そのレイヤーの再構築コストを削減します。この関数は、pretraining_epochs に従って、トレーニング セットに対して固定数のエポックを実行します。

  1. #########################
  2. # モデルの事前トレーニング #  
  3. #########################  
  4. print('...事前トレーニング関数を取得しています')  
  5. pretraining_fns = sda.pretraining_functions ( train_set_x train_set_x =train_set_x,
  6. batch_size batch_size =バッチサイズ)  
  7. print('... モデルの事前トレーニング')  
  8. start_time = timeit.default_timer () です。  
  9. ## レイヤーごとに事前トレーニングする 
  10. 破損レベル= [.1, .2, .3]  
  11. i が範囲内(sda.n_layers)の場合:  
  12. # 事前トレーニングエポックを実行する 
  13. 範囲内のエポックの場合(pretraining_epochs):
  14. # トレーニングセットを実行する
  15. c = []
  16. batch_indexが範囲内(n_train_batches)の場合:
  17. c.append(pretraining_fns[i](インデックス= batch_index ,  
  18. 腐敗=腐敗レベル[i],  
  19. lr = pretrain_lr ))  
  20. print('事前トレーニング層 %i、エポック %d、コスト %f' % (i, epoch, numpy.mean(c, dtype = 'float64' )))  
  21. end_time = timeit .default_timer()
  22. print(('ファイル'の事前トレーニングコード+
  23. os.path.split(__file__)[1] +
  24. ' %.2fm 実行' % ((end_time - start_time) / 60.))、ファイル= sys.stderr )

ここでの微調整サイクルは、多層パーセプトロンの微調整プロセスと非常によく似ています。唯一の違いは、build_finetune_functions によって指定された関数を使用することです。

コードの実行

ユーザーは、次の Python CLI を呼び出してコードを実行できます。

  1. Python コード/SdA.py

デフォルトでは、コードはバッチ サイズ 1 で各レイヤーに対して 15 回の事前トレーニング エポックを実行します。第 1 層のダメージ レベルは 0.1、第 2 層は 0.2、第 3 層は 0.3 です。事前トレーニングの学習率は 0.001、微調整の学習率は 0.1 です。事前トレーニングには 585.01 分かかり、エポックあたり平均 13 分でした。微調整には 36 エポックと 444.2 分かかり、1 エポックあたり平均 12.34 分でした。 *** の検証スコアは 1.39%、テストスコアは 1.3% です。これらの結果は、シングルスレッド GotoBLAS を搭載した Intel Xeon E5430 @ 2.66GHz CPU を搭載したマシンで取得されました。

原文: https://codeburst.io/deep-learning-types-and-autoencoders-a40ee6754663

[この記事は51CTOコラム「Machine Heart」、WeChatパブリックアカウント「Machine Heart(id:almosthuman2014)」によるオリジナル翻訳です]

この著者の他の記事を読むにはここをクリックしてください

<<:  王の英雄を見極める – PM の機械学習初心者の旅

>>:  ディープラーニングにおける多体問題の解決方法

ブログ    
ブログ    
ブログ    

推薦する

高性能な PyTorch はどのように実現されるのでしょうか?経験豊富な専門家がまとめた落とし穴を避ける10のヒント

最小限の労力で最も効率的な PyTorch トレーニングを完了するにはどうすればよいでしょうか? P...

OPPO 広告想起アルゴリズムの実践と調査

1. 背景1. 古いリコールアーキテクチャ上の図の左上部分は、最初にリコールしてからソートする一般的...

人工知能と自然言語処理技術

人工知能技術の発展に伴い、コンピューターを使って外国の文書を翻訳するなど、私たちの生活の多くのアプリ...

...

ディープラーニングの「記憶喪失」に応えて、科学者たちは類似性に基づく重み付けインターリーブ学習を提案し、PNASに掲載された。

人間とは異なり、人工ニューラル ネットワークは新しいことを学習するときに以前に学習した情報をすぐに忘...

...

2020 年の企業向け最高の AI プラットフォーム

企業は長年にわたり、業務と分析を手作業で処理してきましたが、その結果、人件費と事務処理が増加し、最適...

MITは、ニューラルネットワークトレーニングのブラックボックスを自動的に覗くネットワーク解剖フレームワークを提案

MIT の新しいテクノロジーは、視覚データでトレーニングされたニューラル ネットワークの内部の仕組み...

マスク氏がai.comドメイン名を購入しました!ウルトラマンは数千万ドルを費やしてそれを購入し、4ヶ月でアイアンマンに売却した

ai.comドメイン名は、OpenAIが数千万ドルを費やしてマスク氏に購入された。これで、URL a...

...

...

GPT-4 パラメータに関する最新の情報! 1.76兆個のパラメータ、8220億個のMoEモデル、PyTorchの創設者は確信している

皆さん、GPT-4 のパラメータは 1 兆を超える可能性があります。最近、アメリカの有名なハッカーで...

AIが業界全体でビジネス成果をどのように変革しているか

昨年末以来、人工知能の発展の勢いは止められないようです。 GPT-4 のような並外れた認知能力を備え...

2022 RPA認定ランキング

ロボティック・プロセス・オートメーション (RPA) は、ビジネス プロセスの合理化に役立つ重要なテ...

ガベージ コレクション アルゴリズムと JVM ガベージ コレクターの概要

[[199042]]ガベージ コレクション アルゴリズムと JVM ガベージ コレクターの概要は、著...