Skip to content

Commit ade722e

Browse files
committed
Updating doc
1 parent 3bf92d1 commit ade722e

File tree

5 files changed

+387
-59
lines changed

5 files changed

+387
-59
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export(create_keras_functional_spec)
44
export(create_keras_sequential_spec)
55
export(generic_functional_fit)
66
export(generic_sequential_fit)
7+
export(inp_spec)
78
export(keras_losses)
89
export(keras_metrics)
910
export(keras_optimizers)

README.md

Lines changed: 85 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -19,54 +19,48 @@ pak::pak("davidrsch/kerasnip")
1919

2020
## Example
2121

22-
### Example: Building a Sequential MLP from Layer Blocks
22+
### Example 1: Building a Sequential MLP
2323

24-
This example shows the core `kerasnip` workflow for building a model from modular "layer blocks". We will:
25-
1. Define reusable blocks of Keras layers.
26-
2. Create a model specification from these blocks.
27-
3. Fit the model with a fixed architecture.
24+
This example shows the core workflow for building a simple, linear stack of layers using `create_keras_sequential_spec()`.
2825

2926
```r
3027
library(kerasnip)
3128
library(tidymodels)
3229
library(keras3)
3330

3431
# 1. Define Keras layer blocks
35-
# Each block is a function that takes a Keras model object and adds layers.
36-
# The first block in the sequence is responsible for initializing the model.
37-
mlp_input_block <- function(model, input_shape) {
32+
# The first block initializes the model.
33+
input_block <- function(model, input_shape) {
3834
keras_model_sequential(input_shape = input_shape)
3935
}
40-
41-
mlp_dense_block <- function(model, units = 32) {
42-
model |>
43-
layer_dense(units = units, activation = "relu")
36+
# Subsequent blocks add layers.
37+
dense_block <- function(model, units = 32) {
38+
model |> layer_dense(units = units, activation = "relu")
4439
}
45-
46-
mlp_output_block <- function(model) {
40+
# The final block creates the output layer.
41+
output_block <- function(model) {
4742
model |>
4843
layer_dense(units = 1)
4944
}
5045

5146
# 2. Create a spec from the layer blocks
5247
# This creates a new model function, `basic_mlp()`, in your environment.
53-
create_keras_spec(
48+
create_keras_sequential_spec(
5449
model_name = "basic_mlp",
5550
layer_blocks = list(
56-
input = mlp_input_block,
57-
dense = mlp_dense_block,
58-
output = mlp_output_block
51+
input = input_block,
52+
dense = dense_block,
53+
output = output_block
5954
),
6055
mode = "regression"
6156
)
6257

63-
# 3. Use the generated spec to define and fit a model
64-
# We can set the number of dense layers (`num_dense`) and their parameters
65-
# (`dense_units`).
58+
# 3. Use the generated spec to define a model.
59+
# We can set the number of dense layers (`num_dense`) and their parameters (`dense_units`).
6660
spec <- basic_mlp(
6761
num_dense = 2,
6862
dense_units = 64,
69-
epochs = 50,
63+
fit_epochs = 10,
7064
learn_rate = 0.01
7165
) |>
7266
set_engine("keras")
@@ -75,27 +69,70 @@ spec <- basic_mlp(
7569
rec <- recipe(mpg ~ ., data = mtcars) |>
7670
step_normalize(all_numeric_predictors())
7771

78-
wf <- workflow() |>
79-
add_recipe(rec) |>
80-
add_model(spec)
72+
wf <- workflow(rec, spec)
8173

8274
set.seed(123)
8375
fit_obj <- fit(wf, data = mtcars)
8476

8577
# 5. Make predictions
86-
predictions <- predict(fit_obj, new_data = mtcars[1:5, ])
87-
print(predictions)
78+
predict(fit_obj, new_data = mtcars[1:5, ])
8879
#> # A tibble: 5 × 1
8980
#> .pred
9081
#> <dbl>
91-
#> 1 22.6
92-
#> 2 20.9
93-
#> 3 26.1
94-
#> 4 19.7
95-
#> 5 17.8
82+
#> 1 21.3
83+
#> 2 21.3
84+
#> 3 22.8
85+
#> 4 21.4
86+
#> 5 18.7
9687
```
9788

98-
### Example: Tuning a Sequential MLP Architecture
89+
### Example 2: Building a Functional "Fork-Join" Model
90+
91+
For complex, non-linear architectures, use `create_keras_functional_spec()`. This example builds a model where the input is forked into two paths, which are then concatenated.
92+
93+
```r
94+
library(kerasnip)
95+
library(tidymodels)
96+
library(keras3)
97+
98+
# 1. Define blocks. For the functional API, blocks are nodes in a graph.
99+
input_block <- function(input_shape) layer_input(shape = input_shape)
100+
path_block <- function(tensor, units = 16) tensor |> layer_dense(units = units)
101+
concat_block <- function(input_a, input_b) layer_concatenate(list(input_a, input_b))
102+
output_block <- function(tensor) layer_dense(tensor, units = 1)
103+
104+
# 2. Create the spec. The graph is defined by block names and their arguments.
105+
create_keras_functional_spec(
106+
model_name = "forked_mlp",
107+
layer_blocks = list(
108+
main_input = input_block,
109+
path_a = inp_spec(path_block, "main_input"),
110+
path_b = inp_spec(path_block, "main_input"),
111+
concatenated = inp_spec(concat_block, c(path_a = "input_a", path_b = "input_b")),
112+
# The output block must be named 'output'.
113+
output = inp_spec(output_block, "concatenated")
114+
),
115+
mode = "regression"
116+
)
117+
118+
# 3. Use the new spec. Arguments are prefixed with their block name.
119+
spec <- forked_mlp(path_a_units = 16, path_b_units = 8, fit_epochs = 10) |>
120+
set_engine("keras")
121+
122+
# Fit and predict as usual
123+
set.seed(123)
124+
fit(spec, mpg ~ ., data = mtcars) |>
125+
predict(new_data = mtcars[1:5, ])
126+
#> # A tibble: 5 × 1
127+
#> .pred
128+
#> <dbl>
129+
#> 1 19.4
130+
#> 2 19.5
131+
#> 3 21.9
132+
#> 4 18.6
133+
#> 5 17.9
134+
```
135+
### Example 3: Tuning a Sequential MLP Architecture
99136

100137
This example demonstrates how to tune the number of dense layers and the rate of a final dropout layer, showcasing how to tune both architecture and block hyperparameters simultaneously.
101138

@@ -105,30 +142,27 @@ library(tidymodels)
105142
library(keras3)
106143

107144
# 1. Define Keras layer blocks for a tunable MLP
108-
mlp_input_block <- function(model, input_shape) {
145+
input_block <- function(model, input_shape) {
109146
keras_model_sequential(input_shape = input_shape)
110147
}
111-
112-
tunable_dense_block <- function(model, units = 32) {
148+
dense_block <- function(model, units = 32) {
113149
model |> layer_dense(units = units, activation = "relu")
114150
}
115-
116-
tunable_dropout_block <- function(model, rate = 0.2) {
151+
dropout_block <- function(model, rate = 0.2) {
117152
model |> layer_dropout(rate = rate)
118153
}
119-
120-
mlp_output_block <- function(model) {
154+
output_block <- function(model) {
121155
model |> layer_dense(units = 1)
122156
}
123157

124158
# 2. Create a spec from the layer blocks
125-
create_keras_spec(
159+
create_keras_sequential_spec(
126160
model_name = "tunable_mlp",
127161
layer_blocks = list(
128-
input = mlp_input_block,
129-
dense = tunable_dense_block,
130-
dropout = tunable_dropout_block,
131-
output = mlp_output_block
162+
input = input_block,
163+
dense = dense_block,
164+
dropout = dropout_block,
165+
output = output_block
132166
),
133167
mode = "regression"
134168
)
@@ -139,17 +173,15 @@ tune_spec <- tunable_mlp(
139173
dense_units = tune(),
140174
num_dropout = 1,
141175
dropout_rate = tune(),
142-
epochs = 20
176+
fit_epochs = 10
143177
) |>
144178
set_engine("keras")
145179

146-
# 4. Set up a tuning workflow
180+
# 4. Set up and run a tuning workflow
147181
rec <- recipe(mpg ~ ., data = mtcars) |>
148182
step_normalize(all_numeric_predictors())
149183

150-
wf_tune <- workflow() |>
151-
add_recipe(rec) |>
152-
add_model(tune_spec)
184+
wf_tune <- workflow(rec, tune_spec)
153185

154186
# Define the tuning grid.
155187
params <- extract_parameter_set_dials(wf_tune) |>
@@ -167,7 +199,8 @@ folds <- vfold_cv(mtcars, v = 3)
167199
tune_res <- tune_grid(
168200
wf_tune,
169201
resamples = folds,
170-
grid = grid
202+
grid = grid,
203+
control = control_grid(verbose = FALSE)
171204
)
172205

173206
# 6. Show the best architecture
@@ -180,4 +213,4 @@ show_best(tune_res, metric = "rmse")
180213
#> 3 3 64 0.1 rmse standard 3.15 Preprocessor1_Model04
181214
#> 4 1 8 0.1 rmse standard 3.20 Preprocessor1_Model01
182215
#> 5 3 8 0.1 rmse standard 3.22 Preprocessor1_Model03
183-
```
216+
```

man/inp_spec.Rd

Lines changed: 76 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)