% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/create_keras_sequential_spec.R
\name{create_keras_sequential_spec}
\alias{create_keras_sequential_spec}
\title{Create a Custom Keras Sequential Model Specification for Tidymodels}
\usage{
create_keras_sequential_spec(
  model_name,
  layer_blocks,
  mode = c("regression", "classification"),
  ...,
  env = parent.frame()
)
}
\arguments{
\item{model_name}{A character string for the name of the new model
specification function (e.g., "custom_cnn"). This should be a valid R
function name.}

\item{layer_blocks}{A named, ordered list of functions. Each function defines
a "block" of Keras layers. The function must take a Keras model object as
its first argument and return the modified model. Other arguments to the
function will become tunable parameters in the final model specification.}

\item{mode}{A character string, either "regression" or "classification".}

\item{...}{Reserved for future use. Currently not used.}

\item{env}{The environment in which to create the new model specification
function and its associated \code{update()} method. Defaults to the calling
environment (\code{parent.frame()}).}
}
\value{
Invisibly returns \code{NULL}. Its primary side effect is to create a new
model specification function (e.g., \code{my_mlp()}) in the specified
environment and register the model with \code{parsnip} so it can be used within
the \code{tidymodels} framework.
}
\description{
This function acts as a factory to generate a new \code{parsnip} model
specification based on user-defined blocks of Keras layers using the
Sequential API. This is the ideal choice for creating models that are a
simple, linear stack of layers. For models with complex, non-linear
topologies, see \code{\link[=create_keras_functional_spec]{create_keras_functional_spec()}}.
}
\details{
This function generates all the boilerplate needed to create a custom,
tunable \code{parsnip} model specification that uses the Keras Sequential API.

The function inspects the arguments of your \code{layer_blocks} functions
(ignoring special arguments like \code{input_shape} and \code{num_classes})
and makes them available as arguments in the generated model specification,
prefixed with the block's name (e.g., \code{dense_units}).

The new model specification function and its \code{update()} method are created in
the environment specified by the \code{env} argument.
}
\section{Model Architecture (Sequential API)}{

\code{kerasnip} builds the model by applying the functions in \code{layer_blocks} in
the order they are provided. Each function receives the Keras model built by
the previous function and returns a modified version.
\enumerate{
\item The \strong{first block} must initialize the model (e.g., with
\code{keras_model_sequential()}). It can accept an \code{input_shape} argument,
which \code{kerasnip} will provide automatically during fitting.
\item \strong{Subsequent blocks} add layers to the model.
\item The \strong{final block} should add the output layer. For classification, it
can accept a \code{num_classes} argument, which is provided automatically.
}

A key feature of this function is the automatic creation of
\verb{num_\{block_name\}} arguments (e.g., \code{num_hidden}). This allows you to
control how many times each block is repeated, making it easy to tune the
depth of your network.
}

\section{Saving and Reloading Models}{

To save a fitted workflow and reload it in a new R session, use
\code{bundle::bundle()} before saving — this is required to preserve the Keras
model weights:

\if{html}{\out{<div class="sourceCode r">}}\preformatted{library(bundle)
bundled <- bundle(fitted_workflow)
saveRDS(bundled, "model.rds")

# New session:
library(kerasnip); library(bundle)
fitted_workflow <- unbundle(readRDS("model.rds"))
predict(fitted_workflow, new_data = test_data)  # works
}\if{html}{\out{</div>}}

Plain \code{saveRDS()} without \code{bundle()} does not preserve Keras weights, but
\code{predict()} will still auto-register the parsnip model type from metadata
stored on the spec.
}

\examples{
\donttest{
if (requireNamespace("keras3", quietly = TRUE)) {
library(keras3)
library(parsnip)
library(dials)

# 1. Define layer blocks for a complete model.
# The first block must initialize the model. `input_shape` is passed
# automatically.
input_block <- function(model, input_shape) {
  keras_model_sequential(input_shape = input_shape)
}
# A block for hidden layers. `units` will become a tunable parameter.
hidden_block <- function(model, units = 32) {
  model |> layer_dense(units = units, activation = "relu")
}

# The output block. `num_classes` is passed automatically for classification.
output_block <- function(model, num_classes) {
  model |> layer_dense(units = num_classes, activation = "softmax")
}

# 2. Create the spec, providing blocks in the correct order.
create_keras_sequential_spec(
model_name = "my_mlp_seq_spec",
  layer_blocks = list(
    input = input_block,
    hidden = hidden_block,
    output = output_block
  ),
  mode = "classification"
)

# 3. Use the newly created specification function!
# Note the new arguments `num_hidden` and `hidden_units`.
model_spec <- my_mlp_seq_spec(
  num_hidden = 2,
  hidden_units = 64,
  epochs = 10,
  learn_rate = 0.01
)

print(model_spec)
remove_keras_spec("my_mlp_seq_spec")
}
}
}
\seealso{
\code{\link[=remove_keras_spec]{remove_keras_spec()}}, \code{\link[parsnip:add_on_exports]{parsnip::new_model_spec()}},
\code{\link[=create_keras_functional_spec]{create_keras_functional_spec()}}
}
