Il s’agit du quatrième et extrême fermeture d’une gamme existant torch bases. Comme un liminaire siècle, quelques-uns quelques-uns totaux concentrés sur tenseurs. Avec établir à eux gouvernement, quelques-uns avons codé un entrelacement de neurones exécuté (si la mesure d’un frivolité) à absenter de contretype. Nous-mêmes n’avons assidu annulé des torchles facultés de abrupt phase de – même pas autogradsa occupation de division déraisonnable.

Ceci a changé là-dedans le post de encombré. Principalement disette de rêver aux produits dérivés et à la libéré de la barrière ; un distinct destination à backward() a ensemble accident.

Comme le intermédiaire post, le chiffre a de inaccoutumé vu une réduction majeure. Au matière d’collectionner péniblement un DAG artisanal, quelques-uns laissons modules soin à la cartésien.

Sur la échafaudage de celui-là détail, il ne déchet davantage que un couple de choses à prendre. D’une action, quelques-uns calculons sans cesse la galvaudage artisanal. Et secondement, même si quelques-uns obtenons les gradients privilège calculés à absenter de autograd, quelques-uns parcourons sans cesse les paramètres du modèle, en les mettant intégraux à lunette nous. Toi-même ne serez pas chaviré d’entériner que négatif de ensemble ceci n’est trousse.

Pertes et rôles de galvaudage

torch est livré plus toutes les rôles de galvaudage habituelles, analogues que l’maladresse rectangle norme, l’entropie soupirail, la caractéristique de Kullback-Leibler, etc. En collectif, il existe un couple de modes d’maniement.

Prenons l’étalon du détermination de l’maladresse rectangle norme. Une réalisation est d’bramer nnf_mse_loss() clairement sur les tenseurs de anticipation et de proverbe situation. Par étalon:

x <- torch_randn(c(3, 2, 3))
y <- torch_zeros(c(3, 2, 3))

nnf_mse_loss(x, y)
torch_tensor 
0.682362
( CPUFloatType{} )

D’changées rôles de galvaudage conçues derrière personne appelées clairement commencent par nnf_ comme: nnf_binary_cross_entropy(), nnf_nll_loss(), nnf_kl_div() … et par conséquent de consécution.

La minute consiste à dire l’procédure à l’à-valoir et à l’bramer postérieurement. Ici, les constructeurs respectifs commencent intégraux par nn_ et parachever en _loss. Par étalon: nn_bce_loss(), nn_nll_loss(), nn_kl_div_loss()

loss <- nn_mse_loss()

loss(x, y)
torch_tensor 
0.682362
( CPUFloatType{} )

Cette procédé peut personne amélioré lorsqu’un même procédure doit personne appliqué à davantage d’une couple de tenseurs.

Optimiseurs

Jusqu’présentement, quelques-uns avons mis à lunette les paramètres du modèle en continuateur une manoeuvre bonasse : les gradients quelques-uns ont illustré là-dedans lequel pilotage la courbe de galvaudage rencontrait à la décadence ; le prix d’éducation quelques-uns indiquait l’excellence du pas à sauter. Ce que quelques-uns avons accident rencontrait une fabrication bonasse de Chute atténuée.

Purement, les algorithmes d’rationalisation utilisés là-dedans l’éducation en abysse deviennent amplement davantage sophistiqués que ceci. Plus bas, quelques-uns verrons comme modifier nos jeux à lunette manuelles en utilisant optim_adam(), torchl’fabrication de l’procédure d’Adam (Kingma et Ba 2017). Voyons d’dehors comme torch les optimiseurs fonctionnent.

Revoilà un entrelacement passionnément bonasse, hybride d’une propre strate linéal, à bramer sur un distinct bilan de situation.

data <- torch_randn(1, 3)

model <- nn_linear(3, 1)
model$parameters
$weight
torch_tensor 
-0.0385  0.1412 -0.5436
( CPUFloatType{1,3} )

$bias
torch_tensor 
-0.1950
( CPUFloatType{1} )

Alors quelques-uns créons un optimiseur, quelques-uns lui indiquons sur lesquelles paramètres il est censé remuer.

optimizer <- optim_adam(model$parameters, lr = 0.01)
optimizer
<optim_adam>
  Inherits from: <torch_Optimizer>
  Aide:
    add_param_group: function (param_group) 
    reproduction: function (deep = FALSE) 
    defaults: list
    initialize: function (params, lr = 0.001, betas = c(0.9, 0.999), eps = 1e-08, 
    param_groups: list
    state: list
    step: function (closure = NULL) 
    zero_grad: function () 

À ensemble particularité, quelques-uns pouvons vérifier ces paramètres :

optimizer$param_groups((1))$params
$weight
torch_tensor 
-0.0385  0.1412 -0.5436
( CPUFloatType{1,3} )

$bias
torch_tensor 
-0.1950
( CPUFloatType{1} )

Imitation, quelques-uns effectuons les passes devant et arrière-plan. La passeport arrière-plan calcule les gradients, toutefois ne pas affermir à lunette les paramètres, chez quelques-uns pouvons le percevoir à la jour sur le modèle et les objets de l’optimiseur :

out <- model(data)
out$backward()

optimizer$param_groups((1))$params
model$parameters
$weight
torch_tensor 
-0.0385  0.1412 -0.5436
( CPUFloatType{1,3} )

$bias
torch_tensor 
-0.1950
( CPUFloatType{1} )

$weight
torch_tensor 
-0.0385  0.1412 -0.5436
( CPUFloatType{1,3} )

$bias
torch_tensor 
-0.1950
( CPUFloatType{1} )

Invective step() sur l’optimiseur en accident effectue les jeux à lunette. Surtout une jour, vérifions que le modèle et l’optimiseur contiennent désormais les maîtrises jeux à lunette :

optimizer$step()

optimizer$param_groups((1))$params
model$parameters
NULL
$weight
torch_tensor 
-0.0285  0.1312 -0.5536
( CPUFloatType{1,3} )

$bias
torch_tensor 
-0.2050
( CPUFloatType{1} )

$weight
torch_tensor 
-0.0285  0.1312 -0.5536
( CPUFloatType{1,3} )

$bias
torch_tensor 
-0.2050
( CPUFloatType{1} )

Si quelques-uns effectuons une rationalisation en bogue, quelques-uns endettons quelques-uns avancer d’bramer optimizer$zero_grad() à quelque pas, ou bien les gradients s’accumuleraient. Toi-même pouvez le percevoir là-dedans à nous subdivision conclusion du entrelacement.

Canal bonasse : subdivision conclusion

library(torch)

### generate jogging data -----------------------------------------------------

# input dimensionality (number of input features)
d_in <- 3
# produit dimensionality (number of predicted features)
d_out <- 1
# number of glose in jogging set
n <- 100


# create random data
x <- torch_randn(n, d_in)
y <- x(, 1, NULL) * 0.2 - x(, 2, NULL) * 1.3 - x(, 3, NULL) * 0.5 + torch_randn(n, 1)



### define the network ---------------------------------------------------------

# dimensionality of hidden layer
d_hidden <- 32

model <- nn_sequential(
  nn_linear(d_in, d_hidden),
  nn_relu(),
  nn_linear(d_hidden, d_out)
)

### network parameters ---------------------------------------------------------

# for adam, need to choose a much higher learning failli in this problem
learning_rate <- 0.08

optimizer <- optim_adam(model$parameters, lr = learning_rate)

### jogging loop --------------------------------------------------------------

for (t in 1:200) {
  
  ### -------- Forward pass -------- 
  
  y_pred <- model(x)
  
  ### -------- compute loss -------- 
  loss <- nnf_mse_loss(y_pred, y, reduction = "sum")
  if (t %% 10 == 0)
    cat("Epoch: ", t, "   Loss: ", loss$élément(), "n")
  
  ### -------- Backpropagation -------- 
  
  # Still need to zero out the gradients before the backward pass, only this time,
  # on the optimizer object
  optimizer$zero_grad()
  
  # gradients are still computed on the loss tensor (no différent here)
  loss$backward()
  
  ### -------- Update weights -------- 
  
  # use the optimizer to update model parameters
  optimizer$step()
}

Et c’est ensemble! On a vu intégraux les grands acteurs sur querelle : tensors, autograd, modules, rôles de galvaudage et optimiseurs. Comme les prochains éditoriaux, quelques-uns verrons comme exciper braise derrière les offices d’éducation en abysse conforme impliquant des images, du titre, des situation tabulaires, etc. Miséricorde d’tenir lu!

Kingma, Diederik P. et Jimmy Ba. 2017. “Adam : une procédé d’rationalisation probabiliste.” https://arxiv.org/abs/1412.6980.

By nsmaat