ためPyTorchにバイアスを使用して、基本的な機能を近似することは非常に容易である:Rを使用して、基本的な関数近似
library(nnet)
x <- sort(10*runif(50))
y <- sin(x)
nn <- nnet(x, y, size=4, maxit=10000, linout=TRUE, abstol=1.0e-8, reltol = 1.0e-9, Wts = seq(0, 1, by=1/12))
plot(x, y)
x1 <- seq(0, 10, by=0.1)
lines(x1, predict(nn, data.frame(x=x1)), col="green")
predict(nn , data.frame(x=pi/2))
単なる4個のニューロンの1つの隠れ層を有する単純なニューラルネットワークは正弦を近似するのに十分です。 (stackoverflow質問による)
しかし、私はPyTorchで同じものを得ることはできません。
実際、Rで作成されたニューラルネットワークには、入力、4つの隠れ、出力だけでなく、2つの「バイアス」ニューロンも含まれています。上記連結
Link to image: schema of the network built with R
プロットは、以下によって得られる:PyTorchと同じにしようと
library(devtools)
library(scales)
library(reshape)
source_url('https://gist.github.com/fawda123/7471137/raw/cd6e6a0b0bdb4e065c597e52165e5ac887f5fe95/nnet_plot_update.r')
plot.nnet(nn$wts,struct=nn$n, pos.col='#007700',neg.col='#FF7777') ### this plots the graph
plot.nnet(nn$wts,struct=nn$n, pos.col='#007700',neg.col='#FF7777', wts.only=1) ### this prints the weights
は異なるネットワークを生成する:バイアスニューロンが失われています。
以下は、以前にRで行われたことをPyTorchで行う試みです。結果は満足できません。関数は近似されません。最も顕著な違いは、バイアスニューロンが存在しないことです。 「バイアス」ニューロンまたは他の行方不明の詳細を挿入いずれかを介して、所定の関数(ここでは正弦)にネットワークを近似する方法
import torch
from torch.autograd import Variable
import random
import math
N, D_in, H, D_out = 1000, 1, 4, 1
l_x = []
l_y = []
for a in range(1000):
r = random.random()*10
l_x.append([r])
l_y.append([math.sin(r)])
tx = torch.cuda.FloatTensor(l_x)
ty = torch.cuda.FloatTensor(l_y)
x = Variable(tx, requires_grad=False)
y = Variable(ty, requires_grad=False)
w1 = Variable(torch.randn(D_in, H).type(torch.cuda.FloatTensor), requires_grad=True)
w2 = Variable(torch.randn(H, D_out).type(torch.cuda.FloatTensor), requires_grad=True)
learning_rate = 1e-5
for t in range(1000):
y_pred = x.mm(w1).clamp(min=0).mm(w2)
loss = (y_pred - y).pow(2).sum()
if t<10 or t%100==1: print(t, loss.data[0])
loss.backward()
w1.data -= learning_rate * w1.grad.data
w2.data -= learning_rate * w2.grad.data
w1.grad.data.zero_()
w2.grad.data.zero_()
t = [ [math.pi] ]
print(str(t) +" -> "+ str((Variable(torch.cuda.FloatTensor(t))).mm(w1).clamp(min=0).mm(w2).data))
t = [ [math.pi/2] ]
print(str(t) +" -> "+ str((Variable(torch.cuda.FloatTensor(t))).mm(w1).clamp(min=0).mm(w2).data))
?
さらに、「R」が「バイアス」を挿入する理由を理解することが困難です。私はバイアスが "回帰モデルの傍受"に似ているという情報を見つけました - 私はまだそれが明らかでないことがわかります。どんな情報もありがとうございます。
EDIT:結果を得る
例えば、次のように "より完全な" フレームワーク( "車輪を改革しない")を使用することであるけれども:
残念なことにimport torch
from torch.autograd import Variable
import torch.nn.functional as F
import math
N, D_in, H, D_out = 1000, 1, 4, 1
l_x = []
l_y = []
for a in range(1000):
t = (a/1000.0)*10
l_x.append([t])
l_y.append([math.sin(t)])
x = Variable(torch.FloatTensor(l_x))
y = Variable(torch.FloatTensor(l_y))
class Net(torch.nn.Module):
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__()
self.to_hidden = torch.nn.Linear(n_feature, n_hidden)
self.to_output = torch.nn.Linear(n_hidden, n_output)
def forward(self, x):
x = self.to_hidden(x)
x = F.tanh(x) # activation function
x = self.to_output(x)
return x
net = Net(n_feature = D_in, n_hidden = H, n_output = D_out)
learning_rate = 0.01
optimizer = torch.optim.Adam(net.parameters() , lr=learning_rate)
for t in range(1000):
y_pred = net(x)
loss = (y_pred - y).pow(2).sum()
if t<10 or t%100==1: print(t, loss.data[0])
loss.backward()
optimizer.step()
optimizer.zero_grad()
t = [ [math.pi] ]
print(str(t) +" -> "+ str(net(Variable(torch.FloatTensor(t)))))
t = [ [math.pi/2] ]
print(str(t) +" -> "+ str(net(Variable(torch.FloatTensor(t)))))
、このながらコードは正常に動作し、元の "低レベル"コードを期待通りに動作させる問題を解決しません(例えばバイアスを導入するなど)。
class LinearWithInputBias(nn.Linear):
def __init__(self, in_features, out_features, out_bias=True, in_bias=True):
nn.Linear.__init__(self, in_features, out_features, out_bias)
if in_bias:
in_bias = torch.zeros(1, out_features)
# in_bias.normal_() # if you want it to be randomly initialized
self._out_bias = nn.Parameter(in_bias)
def forward(self, x):
out = nn.Linear.forward(self, x)
try:
out = out + self._out_bias
except AttributeError:
pass
return out
は、しかし、あなたのコードでは、追加のバグがあります: -
バイアス用語を追加していないので、 'nn.Linear() '' nn.Module'によって提供されるいくつかの非線形起動関数を使用し、あなたのモードを最適化するために '' torch.optim''を使用しますl?あなたが望むことを簡単にする方法があれば、ホイールを再発明しないでください。 – jdhao
@jdhao、理由は教訓でした:私は最初に "なぜこれはうまくいかないのですか"という混乱がありました。私は偏りがなく、偏見を実装するのが難しいと思っていました。 ライブラリを使用する前に、プロセスの仕組みを理解するためです。 – mdp