Run this notebook online: or Colab:

# 3.3. 线性回归的简洁实现¶

## 3.3.1. 生成数据¶

Section 3.2 中类似，我们首先生成数据。

%load ../utils/djl-imports

NDManager manager = NDManager.newBaseManager();

NDArray trueW = manager.create(new float[]{2, -3.4f});
float trueB = 4.2f;

DataPoints dp = DataPoints.syntheticData(manager, trueW, trueB, 1000);
NDArray features = dp.getX();
NDArray labels = dp.getY();


## 3.3.2. 读取数据集¶

// Saved in the utils file for later use
public ArrayDataset loadArray(NDArray features, NDArray labels, int batchSize, boolean shuffle) {
return new ArrayDataset.Builder()
.setData(features) // set the features
.optLabels(labels) // set the labels
.setSampling(batchSize, shuffle) // set the batch size and random sampling
.build();
}

int batchSize = 10;
ArrayDataset dataset = loadArray(features, labels, batchSize, false);


Batch batch = dataset.getData(manager).iterator().next();
System.out.println(X);
System.out.println(y);
batch.close();

ND: (10, 2) gpu(0) float32
[[ 0.2925, -0.7184],
[ 0.1   , -0.3932],
[ 2.547 , -0.0034],
[ 0.0083, -0.251 ],
[ 0.129 ,  0.3728],
[ 1.0822, -0.665 ],
[ 0.5434, -0.7168],
[-1.4913,  1.4805],
[ 0.1374, -1.2208],
[ 0.3072,  1.1135],
]

ND: (10) gpu(0) float32
[ 7.2342,  5.7411,  9.3138,  5.0536,  3.1772,  8.6284,  7.7434, -3.808 ,  8.6185,  1.0259]


## 3.3.3. 定义模型¶

Model model = Model.newInstance("lin-reg");

SequentialBlock net = new SequentialBlock();
Linear linearBlock = Linear.builder().optBias(true).setUnits(1).build();

model.setBlock(net);


## 3.3.4. 定义损失函数¶

(3.3.1)$L2Loss = \sum_{i = 1}^{n}(y_i - \hat{y_i})^2$
Loss l2loss = Loss.l2Loss();


## 3.3.5. 定义优化算法¶

Tracker lrt = Tracker.fixed(0.03f);
Optimizer sgd = Optimizer.sgd().setLearningRateTracker(lrt).build();


## 3.3.6. Trainer的初始化配置¶

DefaultTrainingConfig config = new DefaultTrainingConfig(l2loss)
.optOptimizer(sgd) // Optimizer (loss function)
.optDevices(manager.getEngine().getDevices(1)) // single GPU

Trainer trainer = model.newTrainer(config);

INFO Training on: 1 GPUs.
INFO Load MXNet Engine Version 1.9.0 in 0.092 ms.


## 3.3.7. 初始化模型参数¶

// First axis is batch size - won't impact parameter initialization
// Second axis is the input size
trainer.initialize(new Shape(batchSize, 2));


## 3.3.8. 运行性能指标¶

Metrics metrics = new Metrics();
trainer.setMetrics(metrics);


## 3.3.9. 训练¶

• 通过调用 trainBatch(batch) 生成预测并计算损失（正向传播）并计算梯度（反向传播）。

• 通过调用 step 函数来更新模型参数。

int numEpochs = 3;

for (int epoch = 1; epoch <= numEpochs; epoch++) {
System.out.printf("Epoch %d\n", epoch);
// Iterate over dataset
for (Batch batch : trainer.iterateDataset(dataset)) {
// Update loss and evaulator
EasyTrain.trainBatch(trainer, batch);

// Update parameters
trainer.step();

batch.close();
}
// reset training and validation evaluators at end of epoch
trainer.notifyListeners(listener -> listener.onEpoch(trainer));
}

Epoch 1
Training:    100% |████████████████████████████████████████| L2Loss: 4.99

INFO Epoch 1 finished.
INFO Train: L2Loss: 4.99

Epoch 2
Training:    100% |████████████████████████████████████████| L2Loss: 0.01

INFO Epoch 2 finished.
INFO Train: L2Loss: 0.01

Epoch 3
Training:    100% |████████████████████████████████████████| L2Loss: 8.58E-05

INFO Epoch 3 finished.
INFO Train: L2Loss: 8.58E-05


Block layer = model.getBlock();
ParameterList params = layer.getParameters();
NDArray wParam = params.valueAt(0).getArray();
NDArray bParam = params.valueAt(1).getArray();

float[] w = trueW.sub(wParam.reshape(trueW.getShape())).toFloatArray();
System.out.printf("Error in estimating w: [%f %f]\n", w[0], w[1]);
System.out.println(String.format("Error in estimating b: %f\n", trueB - bParam.getFloat()));

Error in estimating w: [-0.000193 -0.000954]
Error in estimating b: 0.000900


## 3.3.10. 保存训练模型¶

Path modelDir = Paths.get("../models/lin-reg");
Files.createDirectories(modelDir);

model.setProperty("Epoch", Integer.toString(numEpochs)); // save epochs trained as metadata

model.save(modelDir, "lin-reg");

model

Model (
Name: lin-reg
Model location: /codebuild/output/src036198309/src/github.com/deepjavalibrary/d2l-java-zh/chapter_linear-networks/../models/lin-reg
Data Type: float32
Epoch: 3
)


## 3.3.11. 小结¶

• 我们可以使用 DJL 更简洁地实现模型。

• 在DJL项目里，training.dataset包里有不少数据处理工具，nn 包里定义了大量的神经网络构建层 layerLoss 类定义了许多通用的损失函数。学员们可以根据自己的需要到这些包和类里找合用的工具及函数。

• DJL的 training.initializer 包里有各种模型初始化方法及相应的初始化配置参数供学员参考。

## 3.3.12. 练习¶

1. 参照 DJL 文档，找出其他的损失函数和初始化的方法，使用 L1 损失函数替换 L2Loss

2. 你如何在训练中访问模型的参数？