Pytochを使って関数方式をフィッティングします。


実際には、各大きな深さ学習フレームの背後の原理は、一つのパラメータの数が特に大きい関数を当てはめると理解できます。だから、各フレームは任意の関数に当てはめられます。Pytouchもできます。
このブログでは、y=ax+bのフィッティングを例に(aとbのフィッティングが必要なパラメータ)、Pytouchでどのように関数を当てはめるかを説明します。
一、フィッティングネットワークの定義
1、普通の神経ネットワークの最適化の流れを観察する

#     
net = ...
#      
optimizer = torch.optim.Adam(net.parameters(), lr=0.001, weight_decay=0.0005)
#       
loss_op = torch.nn.MSELoss(reduction='sum')
#   
for step, (inputs, tag) in enumerate(dataset_loader):
 #     
 outputs = net(inputs)
 #     
 loss = loss_op(tag, outputs)
 #     
 optimizer.zero_grad()
 #     
 loss.backward()
 #     
 optimizer.step()
上のコードは一般的な流れです。Pytouch内蔵の最適化器を使用するためには、関数parameters(最適化が必要なパラメータを返す)とforward(前向き伝搬)を定義する必要があります。GPU最適化をサポートするためには、キューダとcpuの2つの関数を実現し、パラメータをメモリからGPUにコピーしたり、GPUからメモリにコピーしたりする必要があります。
以上の要求に基づいて、ネットワークの定義は以下のようになる。

class Net:
  def __init__(self):
    #           
    pass

  def cuda(self):
    #      GPU
    pass

  def cpu(self):
    #         
    pass

  def forward(self, inputs):
   #       ,      inputs      
    pass

  def parameters(self):
   #     
    pass
フィットデータ量が大きい場合は、GPUを使って加速することもできます。英偉達グラフィックカードがなければ、キューダとcpuの二つの関数は実現できません。
2、ネットワークを初期化する
本稿の目的を振り返ってみますと、フィッティング:y=ax+bですので、__init_関数にはaとbの2つのパラメータを定義する必要があります。また、parameters、cpu、cudaを実現するためには、属性を定義する必要があります。parametersと_u ugpu:

  def __init__(self):
    # y = a*x + b
    self.a = torch.rand(1, requires_grad=True) #   a
    self.b = torch.rand(1, requires_grad=True) #   b
    self.__parameters = dict(a=self.a, b=self.b) #     
    self.___gpu = False #     gpu   
フィットするパラメータは、0に初期化できません。乱数の値を使うのが一般的です。まだrequires_を必要とします。gradパラメータはTrueに設定されています。これは後方伝搬をサポートするためです。
3、前向きに伝える

  def forward(self, inputs):
    return self.a * inputs + self.b
非常に簡単です。入力inputに基づいて出力を計算します。この例ではy=ax+bを計算します。計算が終わったら計算の結果を返してください。
4、パラメータをGPUに転送する
GPUをサポートしてフィッティングを加速するためには、パラメータをGPUに転送する必要があり、パラメータ辞書の更新が必要です。parameters:

  def cuda(self):
    if not self.___gpu:
      self.a = self.a.cuda().detach().requires_grad_(True) #  a   gpu
      self.b = self.b.cuda().detach().requires_grad_(True) #  b   gpu
      self.__parameters = dict(a=self.a, b=self.b) #     
      self.___gpu = True #     ,         gpu 
    #   self,       
    return self
パラメータaとbは、先にdetachを呼び出してからrequires auを呼び出します。grad_,エラーを避けるために、ライセValueError(「can't optimize a non-leaf Tensor」)です。
4、パラメータをメモリに転送する
キューダ関数と似ていますが、説明はあまりしません。

  def cpu(self):
    if self.___gpu:
      self.a = self.a.cpu().detach().requires_grad_(True)
      self.b = self.b.cpu().detach().requires_grad_(True)
      self.__parameters = dict(a=self.a, b=self.b)
      self.___gpu = False
    return self
5、ネットワークパラメータに戻る
Pytouch内蔵の最適化器を使用するためには、parameters関数を実現し、Pytouch内の実現を観察します。

  def parameters(self, recurse=True):
    r"""...
    """
    for name, param in self.named_parameters(recurse=recurse):
      yield param
実際には、yieldを使ってネットワークのすべてのパラメータに戻りますので、この例では以下のように実現されます。

  def parameters(self):
    for name, param in self.__parameters.items():
      yield param
完全な実現は後ろに置いておきます。
二、テスト
1、試験データの生成

def main():
  #       
  x = np.linspace(1, 50, 50)
  #   a、b
  a = 2
  b = 1
  #   y
  y = a * x + b
  #    Tensor
  x = torch.from_numpy(x.astype(np.float32))
  y = torch.from_numpy(y.astype(np.float32))
2、ネットワークを定義する

 #     
  net = Net()
  #      
  optimizer = torch.optim.Adam(net.parameters(), lr=0.001, weight_decay=0.0005)
  #       
  loss_op = torch.nn.MSELoss(reduction='sum')
3、GPUにデータを転送する(オプション)

 #    GPU
  if torch.cuda.is_available():
    x = x.cuda()
    y = y.cuda()
    net = net.cuda()
4、最適化器と損失関数を定義する
GPUを使って加速するなら、最適化器はネットワークのパラメータをGPUに転送してから定義しなければなりません。そうでないと、最適化器の中のパラメータですか?それともメモリの中のパラメータですか?GPUに伝わるパラメータは更新されません。この言葉はコードによって理解できます。

 #      
  optimizer = torch.optim.Adam(net.parameters(), lr=0.001, weight_decay=0.0005)
  #       
  loss_op = torch.nn.MSELoss(reduction='sum')
5、フィッティング(も最適化)

#     20001 
  for i in range(1, 20001, 1):
   #     
    out = net.forward(x)
 #     
    loss = loss_op(y, out)
 #     (    )
    optimizer.zero_grad()
 #     ,    
    loss.backward()
 #     
    optimizer.step()
 #      numpy 
    loss_numpy = loss.cpu().detach().numpy()
    if i % 1000 == 0: #  1000       
      print(i, loss_numpy)

    if loss_numpy < 0.00001: #       0.00001
     #     
     a = net.a.cpu().detach().numpy()
     b = net.b.cpu().detach().numpy()
      print(a, b)
      #   
      exit()
6、完全な例示コード

# coding=utf-8
from __future__ import absolute_import, division, print_function
import torch
import numpy as np


class Net:
  def __init__(self):
    # y = a*x + b
    self.a = torch.rand(1, requires_grad=True) #   a
    self.b = torch.rand(1, requires_grad=True) #   b
    self.__parameters = dict(a=self.a, b=self.b) #     
    self.___gpu = False #     gpu   

  def cuda(self):
    if not self.___gpu:
      self.a = self.a.cuda().detach().requires_grad_(True) #  a   gpu
      self.b = self.b.cuda().detach().requires_grad_(True) #  b   gpu
      self.__parameters = dict(a=self.a, b=self.b) #     
      self.___gpu = True #     ,         gpu 
    #   self,       
    return self

  def cpu(self):
    if self.___gpu:
      self.a = self.a.cpu().detach().requires_grad_(True)
      self.b = self.b.cpu().detach().requires_grad_(True)
      self.__parameters = dict(a=self.a, b=self.b) #     
      self.___gpu = False
    return self

  def forward(self, inputs):
    return self.a * inputs + self.b

  def parameters(self):
    for name, param in self.__parameters.items():
      yield param


def main():

  #       
  x = np.linspace(1, 50, 50)

  #   a、b
  a = 2
  b = 1

  #   y
  y = a * x + b

  #    Tensor
  x = torch.from_numpy(x.astype(np.float32))
  y = torch.from_numpy(y.astype(np.float32))

  #     
  net = Net()

  #    GPU
  if torch.cuda.is_available():
    x = x.cuda()
    y = y.cuda()
    net = net.cuda()

  #      
  optimizer = torch.optim.Adam(net.parameters(), lr=0.001, weight_decay=0.0005)

  #       
  loss_op = torch.nn.MSELoss(reduction='sum')

  #     20001 
  for i in range(1, 20001, 1):
    #     
    out = net.forward(x)
    #     
    loss = loss_op(y, out)
    #     (    )
    optimizer.zero_grad()
    #     ,    
    loss.backward()
    #     
    optimizer.step()
    #      numpy 
    loss_numpy = loss.cpu().detach().numpy()
    if i % 1000 == 0: #  1000       
      print(i, loss_numpy)

    if loss_numpy < 0.00001: #       0.00001
      #     
      a = net.a.cpu().detach().numpy()
      b = net.b.cpu().detach().numpy()
      print(a, b)
      #   
      exit()


if __name__ == '__main__':
  main()
以上のPytouchを使って関数をフィッティングする方式は小編集が皆さんに提供した内容の全部です。参考にしてもらいたいです。どうぞよろしくお願いします。