R语言数学建模(三)—— 模型工作流

R语言数学建模(三)—— 模型工作流


文章目录

  • R语言数学建模(三)—— 模型工作流
  • 前言
  • 一、模型工作流
    • 1.1 模型的起点和终点在哪里?
    • 1.2 Workflow基础
    • 1.3 将原始变量添加到`workflow()`
    • 1.4 `workflow()`如何使用formula
      • 基于树的模型
      • 1.4.1 特殊公式和内联函数
    • 1.5 一次创建多个工作流
    • 1.6 评估测试集
  • 总结


前言

前面,我们学习了tidymodels包用于建模的基本流程,学习了parsnip包用于模型的定义及拟合和预测。有了它们,我们的对于不同模型的使用更加的标准化和格式化了。为了进一步规范化建模的过程,tidymodels包还提供了模型工作流的概念,可以将建模的流程封装进一套工作流程中,这样的数学建模过程会更加的系统,也更有利于后续的维护和修改。

一、模型工作流

1.1 模型的起点和终点在哪里?

目前为止,我们使用"模型"术语的时候,我们指的是将一些预测因素与一个或者多个结果联系起来的结构方程。让我们再看看线性回归的例子。其结果数据表示为 y i y_{i} yi,其中训练集有 i = 1 … n i=1 \dots n i=1n个样本。假设有 p p p预测因子 x i 1 , … , x i p x_{i1} ,\dots , x_{ip} xi1,,xip在模型中使用。线性回归产生了一个模型方程:

y ^ i = β ^ 0 + β ^ 1 x i 1 + ⋯ + β ^ p x i p \hat y_{i} =\hat\beta_{0}+\hat\beta_{1}x_{i1}+\dots+\hat\beta_{p}x_{ip} y^i=β^0+β^1xi1++β^pxip

虽然这是一个线性模型,但他只是在参数上是线性的。预测因子可以是非线性项(比如 log ⁡ ( x i ) \log_{}{(x_{i})} log(xi)

对于一些直截了当的数据集,拟合模型本身可能就是整个过程。然而在模型匹配之前,通常会出现各种选择和其他步骤:

  • 数据的预处理步骤,可能开始的数据并不能完全作为预测因子 p p p

  • 有时,一个重要的预测因子的值可能会丢失。可以使用数据中的其他值来推算缺失的值,而不是从数据集中删除该样本。

  • 改变预测因子的尺度可能是有益的。如果没有关于新尺度应该是什么的先验信息(priori information),我们可以使用统计变换技术、现有数据以及一些优化准则来估计合适的尺度。其他的转换方式,如PCA。

虽然这些示例与模型拟合之前发生的步骤相关,但是也可能存在在模型创建之后发生的操作。当创建分类模型时,其中的结构是二元(例如:)的,习惯上使用50%的概率截止值来创建离散类别预测,也称之为硬预测。例如,分类模型可能估计的概率为62%,用典型的默认模型,硬预测将会是事件()。然而,该模型可能需要更多的集中于减少假阳性结果(即将真实的归类为)。要做到这一点一种方法是,将cutoff提高到高于50%。这增加了将新样本称为所需的证据水平。虽然这会降低真阳性率(不好的),但是他在减少假阳性率上会有更加显著的效果。cutoff值的选择应该使用数据进行优化。这是一个后处理的步骤的示例,它对模型的工作效果有很大的影响,即使它不包含在模型拟合步骤中。

重要的是关注更广泛的建模过程,而不是只拟合用于估计参数的特定模型。这一更广泛的建模过程包含任何预处理步骤、模型本身的匹配以及潜在的后处理活动。在这里,我们把这个更全面的概念称为模型工作流,并强调如何处理其所有组件以生成最终的模型方程式。

将数据分析的分析组件绑定在一起还有另一个重要原因。后续将演示如何准确测量性能,以及如何优化结构参数(即模型调整)。为了正确量化训练集上的模型性能,后续会提倡使用重采样的方法。为了正确做到这一点,不应该将分析的任何数据驱动部分排除在验证之外。为此,工作流必须包括所有重要的评估步骤。

1.2 Workflow基础

workflow包允许用户将建模与数据预处理结合起来。让我们以Ames数据为例进行一个简单的线性模型:

library(tidymodels)
tidymodels_prefer()lm_model <- linear_reg() |> set_engine("lm")

一个workflow需要一个parsnip模型对象:

lm_wflow <- workflow() |> add_model(lm_model)lm_wflow
#> ══ Workflow ════════════════════════════════════════════════════════════════════
#> Preprocessor: None
#> Model: linear_reg()
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> Linear Regression Model Specification (regression)
#> 
#> Computational engine: lm

如果我们的模型是很简单的,一个标准的R公式就可以用于预处理:

lm_wflow <- lm_wflow |> add_formula(Sale_Price ~ Longitude + Latitude)lm_wflow
#> ══ Workflow ════════════════════════════════════════════════════════════════════
#> Preprocessor: Formula
#> Model: linear_reg()
#> 
#> ── Preprocessor ────────────────────────────────────────────────────────────────
#> Sale_Price ~ Longitude + Latitude
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> Linear Regression Model Specification (regression)
#> 
#> Computational engine: lm

Workflows有fit()方法来用于创建模型:

# 拆分ames数据
data(ames)
ames_split <- ames |> mutate(Sale_Price = log10(Sale_Price)) |> initial_split(prop = 0.80, strata = Sale_Price)
ames_train <- training(ames_split)
ames_test <- testing(ames_split)
# fit
lm_fit <- fit(lm_wflow, ames_train)
lm_fit
#> ══ Workflow [trained] ══════════════════════════════════════════════════════════
#> Preprocessor: Formula
#> Model: linear_reg()
#> 
#> ── Preprocessor ────────────────────────────────────────────────────────────────
#> Sale_Price ~ Longitude + Latitude
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> 
#> Call:
#> stats::lm(formula = ..y ~ ., data = data)
#> 
#> Coefficients:
#> (Intercept)    Longitude     Latitude  
#>    -313.623       -2.074        2.965

我们也可以使用predict()

predict(lm_fit, ames_test |> slice(1:3))
#> # A tibble: 3 × 1
#>   .pred
#>   <dbl>
#> 1  5.23
#> 2  5.29
#> 3  5.28

模型和预处理器都可以删除或者更新:

lm_fit |> update_formula(Sale_Price ~ Longitude)
#> ══ Workflow ════════════════════════════════════════════════════════════════════
#> Preprocessor: Formula
#> Model: linear_reg()
#> 
#> ── Preprocessor ────────────────────────────────────────────────────────────────
#> Sale_Price ~ Longitude
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> Linear Regression Model Specification (regression)
#> 
#> Computational engine: lm

注意输出在这个更新后被移除。

1.3 将原始变量添加到workflow()

另一个将数据传递给模型的接口是add_variables()函数,它是由类dplyr的语法来选择变量。该函数有两个主要参数:结果和预测因子(outcomespredictors)它们使用c()来获取多个选择器:

lm_wflow <- lm_wflow |> remove_formula() |> add_variables(outcomes = Sale_Price, predictors = c(Longitude, Latitude))
lm_wflow
#> ══ Workflow ════════════════════════════════════════════════════════════════════
#> Preprocessor: Variables
#> Model: linear_reg()
#> 
#> ── Preprocessor ────────────────────────────────────────────────────────────────
#> Outcomes: Sale_Price
#> Predictors: c(Longitude, Latitude)
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> Linear Regression Model Specification (regression)
#> 
#> Computational engine: lm

predictors还可以使用通用选择器:

predictors = c(ends_with("tude"))

有一点值得注意,预测因子参数中意外指定的任何结果列都将被默认删除。因此可以使用everything()来指定所有除结果列外的列:

predictors = everything()

模型进行匹配时,会将这些未更改的数据组装到一个数据框中,将其传递给底层函数:

fit(lm_wflow, ames_train)
#> ══ Workflow [trained] ══════════════════════════════════════════════════════════
#> Preprocessor: Variables
#> Model: linear_reg()
#> 
#> ── Preprocessor ────────────────────────────────────────────────────────────────
#> Outcomes: Sale_Price
#> Predictors: c(Longitude, Latitude)
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> 
#> Call:
#> stats::lm(formula = ..y ~ ., data = data)
#> 
#> Coefficients:
#> (Intercept)    Longitude     Latitude  
#>    -313.623       -2.074        2.965

如果你希望底层建模方法按照它通常处理数据的方式进行操作,那么add_variables()会是一个有用的接口。下面我们将看到它促进了更加复杂的建模规范。

后续,将介绍一个功能更强大的预处理器(recipe),它也可以添加到workflow中。

1.4 workflow()如何使用formula

R中的公式(formula)有多种用途。其一就是将原始数据正确编码为可供分析的格式。这可能涉及到执行内联转换(如: log ⁡ ( x ) \log_{}{(x)} log(x))、创建虚拟变量列、创建交互或其他扩展列,等等。然而,许多统计方法需要不同类型的编码:

  • 基于树的模型的大多数包使用formula接口,但不将分类预测因子编码为虚拟变量。

  • 包可以使用特殊的内联函数来告诉模型如何在分析中处理预测因子。例如,在生存分析模型中,一个公式术语,如strata(site)将指示site列是分层变量。这意味着它不能被视为常规的预测因子,并且在模型中没有相应的位置参数估计。

  • 一些R包以基本R函数无法解析或执行的方式扩展了公式。在多级模型(如:混合模型或者分层贝叶斯模型)中,诸如(week | subject)之类的模型术语指示的week列是随机效应,其对于subject列的每个值具有不同的斜率参数估计。

工作流是一个通用界面。当使用add_formula()时,由于预处理依赖模型,因此工作流会尝试在任何可能的情况下模拟底层模型操作。如果不可能,则公式处理不应对公式中使用的列执行任何操作。

基于树的模型

当我们将树拟合到数据时,parsnip包理解建模函数会做什么。例如,如果使用rangerrandomForest包拟合随机森林模型,则工作流知道作为预测因子列的因子应该保持不变。

作为反例,使用xgboost包创建的boosted树要求用户从预测因子中创建虚拟变量(因为xgboost::xgb.train()不会)。该需求被嵌入到模型规范对象中,并且使用xgboost的工作流会为该引擎创建指示符列。还要注意的是,用于Boost树的另一个引擎C5.0不需要虚拟变量,因此工作流不会生成任何变量。

1.4.1 特殊公式和内联函数

许多多层级模型已经根据lme4包中设计的公式规范进行了标准化。例如,为了适应对受试者具有随机影响的回归模型,我们将使用以下公式:

library(lme4)
#> Loading required package: Matrix
#> 
#> Attaching package: 'Matrix'
#> The following objects are masked from 'package:tidyr':
#> 
#>     expand, pack, unpack
data(Orthodont, package = "nlme")lmer(distance ~ Sex + (age | Subject), data = Orthodont)
#> Linear mixed model fit by REML ['lmerMod']
#> Formula: distance ~ Sex + (age | Subject)
#>    Data: Orthodont
#> REML criterion at convergence: 471.1635
#> Random effects:
#>  Groups   Name        Std.Dev. Corr 
#>  Subject  (Intercept) 7.3912        
#>           age         0.6943   -0.97
#>  Residual             1.3100        
#> Number of obs: 108, groups:  Subject, 27
#> Fixed Effects:
#> (Intercept)    SexFemale  
#>      24.517       -2.145

这样做的效果就是,每个subject将有一个估计的age截距和斜率参数。

问题是使用标准的R方法不能正确的处理这个公式:

model.matrix(distance ~ Sex + (age | Subject), data = Orthodont)
#> Warning in Ops.ordered(age, Subject): '|' is not meaningful for ordered factors
#>      (Intercept) SexFemale age | SubjectTRUE
#> attr(,"assign")
#> [1] 0 1 2
#> attr(,"contrasts")
#> attr(,"contrasts")$Sex
#> [1] "contr.treatment"
#> 
#> attr(,"contrasts")$`age | Subject`
#> [1] "contr.treatment"

结果是0行数据框。

问题是,特殊公式必须由底层的包代码处理,而不是标准的model.mateix()方法。

即使该公式可以与model.matrix()一起使用,这仍然会带来问题,因为该公式还指定了模型的统计属性。

工作流中的解决方案是一个可选的补充模型公式,可以传递给add_model()add_variables()规范提供列名,然后在add_model()中设置模型的实际公式:

library(multilevelmod)multilevel_spec <- linear_reg() |> set_engine("lmer")multilevel_workflow <- workflow() |> add_variables(outcomes = distance, predictors = c(Sex, age, Subject)) |> add_model(multilevel_spec,formula = distance ~ Sex + (age | Subject))multilevel_fit <- fit(multilevel_workflow, data = Orthodont)
multilevel_fit
#> ══ Workflow [trained] ══════════════════════════════════════════════════════════
#> Preprocessor: Variables
#> Model: linear_reg()
#> 
#> ── Preprocessor ────────────────────────────────────────────────────────────────
#> Outcomes: distance
#> Predictors: c(Sex, age, Subject)
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> Linear mixed model fit by REML ['lmerMod']
#> Formula: distance ~ Sex + (age | Subject)
#>    Data: data
#> REML criterion at convergence: 471.1635
#> Random effects:
#>  Groups   Name        Std.Dev. Corr 
#>  Subject  (Intercept) 7.3912        
#>           age         0.6943   -0.97
#>  Residual             1.3100        
#> Number of obs: 108, groups:  Subject, 27
#> Fixed Effects:
#> (Intercept)    SexFemale  
#>      24.517       -2.145

我们甚至可以使用前面提到的strata()函数从survival包中进行分析:

library(censored)
#> Loading required package: survivalparametric_spec <- survival_reg()parametric_workflow <- workflow() |> add_variables(outcomes = c(fustat, futime), predictors = c(age, rx)) |> add_model(parametric_spec,formula = Surv(futime, fustat) ~ age + strata(rx))parametric_fit <- fit(parametric_workflow, data = ovarian)
parametric_fit
#> ══ Workflow [trained] ══════════════════════════════════════════════════════════
#> Preprocessor: Variables
#> Model: survival_reg()
#> 
#> ── Preprocessor ────────────────────────────────────────────────────────────────
#> Outcomes: c(fustat, futime)
#> Predictors: c(age, rx)
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> Call:
#> survival::survreg(formula = Surv(futime, fustat) ~ age + strata(rx), 
#>     data = data, model = TRUE)
#> 
#> Coefficients:
#> (Intercept)         age 
#>  12.8734120  -0.1033569 
#> 
#> Scale:
#>      rx=1      rx=2 
#> 0.7695509 0.4703602 
#> 
#> Loglik(model)= -89.4   Loglik(intercept only)= -97.1
#>  Chisq= 15.36 on 1 degrees of freedom, p= 8.88e-05 
#> n= 26

注意这两个调用中是如何使用模型特定公式的。

1.5 一次创建多个工作流

在某些情况下,数据需要多次尝试才能找到合适的模型。比如:

  • 对于预测模型,建议评估各种不同的模型类型。这要求用户创建多个模型规格。

  • 模型的一系列测试通常从一组扩展的预测因子开始。将这个完整的模型与相同模型的序列进行比较,该序列依次删除每个预测因子。使用基本的假设检验方法或经验验证方法,可以分离和评估每个预测因子的效果。

在这些情况以及其他情况下,从不同的预处理器和/或模型规范中创建大量工作流会非常乏味和繁重。为了解决这些问题,workflowset包提供了创建工作流组合。预处理器列表可以和模型规范列表组合从而产生一组工作流。

假设我们需要在Ames数据表中表示房屋位置的不同方式。我们可以创建一组formulas来捕捉这些预测因子:

location <- list(longitude = Sale_Price ~ Longitude,latitude = Sale_Price ~ Latitude,coords = Sale_Price ~ Longitude + Latitude,neighborhood = Sale_Price ~ Neighborhood
)

我们可以使用workflow_set()函数来将这些表示与一个或多个模型交叉。我们将使用前面的线性模型规范来演示:

library(workflowsets)
location_models <- workflow_set(preproc = location, models = list(lm = lm_model))
location_models
#> # A workflow set/tibble: 4 × 4
#>   wflow_id        info             option    result    
#>   <chr>           <list>           <list>    <list>    
#> 1 longitude_lm    <tibble [1 × 4]> <opts[0]> <list [0]>
#> 2 latitude_lm     <tibble [1 × 4]> <opts[0]> <list [0]>
#> 3 coords_lm       <tibble [1 × 4]> <opts[0]> <list [0]>
#> 4 neighborhood_lm <tibble [1 × 4]> <opts[0]> <list [0]>
location_models$info[[1]]
#> # A tibble: 1 × 4
#>   workflow   preproc model      comment
#>   <list>     <chr>   <chr>      <chr>  
#> 1 <workflow> formula linear_reg ""
extract_workflow(location_models, id = "coords_lm")
#> ══ Workflow ════════════════════════════════════════════════════════════════════
#> Preprocessor: Formula
#> Model: linear_reg()
#> 
#> ── Preprocessor ────────────────────────────────────────────────────────────────
#> Sale_Price ~ Longitude + Latitude
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> Linear Regression Model Specification (regression)
#> 
#> Computational engine: lm

工作流集主要是设计用于重新采样,这将在后续学习进行讨论。optionresult列必须是由重新排序产生的特定类型的对象。我们将在后续学习中讨论其中的更多细节。

同时,让我们为每个公式创建模型匹配,并将他们保存在一个名为fit的新列中。我们将使用基本的dplyrpurrr操作:

location_models <- location_models |> mutate(fit = map(info, ~ fit(.x$workflow[[1]], ames_train)))
location_models
#> # A workflow set/tibble: 4 × 5
#>   wflow_id        info             option    result     fit       
#>   <chr>           <list>           <list>    <list>     <list>    
#> 1 longitude_lm    <tibble [1 × 4]> <opts[0]> <list [0]> <workflow>
#> 2 latitude_lm     <tibble [1 × 4]> <opts[0]> <list [0]> <workflow>
#> 3 coords_lm       <tibble [1 × 4]> <opts[0]> <list [0]> <workflow>
#> 4 neighborhood_lm <tibble [1 × 4]> <opts[0]> <list [0]> <workflow>
location_models$fit[[1]]
#> ══ Workflow [trained] ══════════════════════════════════════════════════════════
#> Preprocessor: Formula
#> Model: linear_reg()
#> 
#> ── Preprocessor ────────────────────────────────────────────────────────────────
#> Sale_Price ~ Longitude
#> 
#> ── Model ───────────────────────────────────────────────────────────────────────
#> 
#> Call:
#> stats::lm(formula = ..y ~ ., data = data)
#> 
#> Coefficients:
#> (Intercept)    Longitude  
#>    -177.334       -1.949

这里使用的是purrr函数来映射模型,另外更简单友好的方式将在后续介绍。

1.6 评估测试集

假设模型开发已经完成并且确定了最终的模型。有一个last_fit()的方便函数可以对模型进行fit使其适合整个训练集,并使用测试集对其进行评估。

lm_wflow为例,我们可以将模型和初始训练集/测试集拆分传递给函数:

final_lm_res <- last_fit(lm_wflow, ames_split)
final_lm_res
#> # Resampling results
#> # Manual resampling 
#> # A tibble: 1 × 6
#>   splits             id               .metrics .notes   .predictions .workflow 
#>   <list>             <chr>            <list>   <list>   <list>       <list>    
#> 1 <split [2342/588]> train/test split <tibble> <tibble> <tibble>     <workflow>

注意:last_fit()接受数据拆分作为输入,而不是数据框。此函数用拆分来生成用于最终fitting和evaluation的训练和测试集

.workflow列包含拟合的工作流,并且可以从结果中提出:

fitted_lm_wflow <- extract_workflow(final_lm_res)

同时,collect_metrics()collect_predictions()分别提供对性能指标和预测的访问。

collect_metrics(final_lm_res)
#> # A tibble: 2 × 4
#>   .metric .estimator .estimate .config             
#>   <chr>   <chr>          <dbl> <chr>               
#> 1 rmse    standard       0.164 Preprocessor1_Model1
#> 2 rsq     standard       0.189 Preprocessor1_Model1
collect_predictions(final_lm_res) |> slice(1:5)
#> # A tibble: 5 × 5
#>   id               .pred  .row Sale_Price .config             
#>   <chr>            <dbl> <int>      <dbl> <chr>               
#> 1 train/test split  5.22     2       5.02 Preprocessor1_Model1
#> 2 train/test split  5.21     4       5.39 Preprocessor1_Model1
#> 3 train/test split  5.28     5       5.28 Preprocessor1_Model1
#> 4 train/test split  5.27     8       5.28 Preprocessor1_Model1
#> 5 train/test split  5.28    10       5.28 Preprocessor1_Model1

关于last_fit()的更多使用内容,在后续会展开介绍。

在使用验证集时,last_fit()有一个名为add_validation_set的参数,用于指定是仅根据训练集(default)还是根据训练集和验证集的组合来训练最终模型。

总结

通过这部分的学习,我们学到了如何对模型创建工作流来管理建模的过程。workflow包括了模型使用的全过程,首先是数据预处理过程,使用add_variables对于输入数据进行分类输入,下一节我们将学习一个更加全面的预处理器——recipe,届时将会进行更加复杂的数据预处理。然后,我们使用add_model把模型设置加入工作流中,这时我们可以通过设置formula参数将预测因子的处理模式加入其中。最后可以使用fit或者last_fit对模型进行拟合,即可得到一个模型的应用实例(注意输入类型)。另外,某些情况下,可能需要一次创建多个工作流,这就需要调用workflowset包,通过设置参数列表来同时创建多条工作流,然后使用索引来分别进行调用即可。

学习之路,道阻且长。我常常会在学习的道路上质疑自己,也常常自问,学这些干什么,对别人来说可能这些就像1+1一样简单。但是,不去了解就永远不会了解,会的越多不会的就越多,让我们收起浮躁的心情去学习。要知道,流水不争先,争的是滔滔不绝。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/721717.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构和算法初阶(C语言)】复杂链表(随机指针,随机链表的复制)题目详解+链表顺序表结尾

目录 1.随机链表的复制 1.2题目描述 1.3题目分析 1.4解题&#xff1a; 2.顺序表和链表对比 2.1cpu高速缓存利用率 3.结语 1.随机链表的复制 一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random 该指针可以指向链表中的任何节点或空节点。 1.2题目描…

Godot自定义控件样式语法解析

前言 本篇原始文章写于2023年8月7日&#xff0c;存储在我的语雀文档中。但是语雀分享有诸多不便&#xff0c;为了让更多Godoter更轻松的搜到和看到&#xff0c;就转过来了。 这个项目我上传了Github&#xff0c;后续会贴上链接。 概述 Godot控件体系存在的问题之一就是样式无…

【pyinstaller打包记录】Windows系统打包exe后,onnxruntime报警告(Init provider bridge failed)

简介 PyInstaller 是一个用于将 Python 程序打包成可执行文件&#xff08;可执行程序&#xff09;的工具。它能够将 Python 代码和其相关的依赖项&#xff08;包括 Python 解释器、依赖的模块、库文件等&#xff09;打包成一个独立的可执行文件&#xff0c;方便在不同环境中运行…

SQL索引优化

自己学习日志 索引优化 为搜索字段、排序字段、select查询列&#xff0c;创建合适的索引&#xff0c;不过要考虑数据的业务厂家&#xff1a;查询多还是增删多 尽量建立组合索引并注意组合索引的创建顺序&#xff0c;按照顺序组织查询条件&#xff0c;尽量将筛选颗粒度大的条件…

凌风 TEMU工具箱 抢仓 库存销售数据利润计算 选品监控采集上品 一网打尽

凌风TEMU工具箱介绍 一、安装教程1、下载方式2、环境准备3、安装步骤3.1、插件安装3.2、客户端安装 4、启动软件 二、使用教程一&#xff1a;登录注册激活方法2.1 注册登录2.2 激活方式 &#xff08;激活码激活&#xff09;2.3 绑定店铺 二&#xff1a;使用方法&#xff1a;功能…

Android Gradle开发与应用 (四) : Gradle构建与生命周期

1. 前言 前几篇文章&#xff0c;我们对Gradle中的基本知识&#xff0c;包括Gradle项目结构、Gradle Wrapper、GradleUserHome、Groovy基础语法、Groovy语法概念、Groovy闭包等知识点&#xff0c;这篇文章我们接着来介绍Gradle构建过程中的知识点。 2. Project : Gradle中构建…

揭秘大气颗粒物与VOCs:PMF源解析技术全解析

在现今日益严峻的环境问题中&#xff0c;大气颗粒物和臭氧污染尤为突出&#xff0c;它们不仅深刻影响着全球气候和生态环境&#xff0c;更对人体健康构成了严重威胁。为了有效应对这一挑战&#xff0c;我们首先需要深入了解颗粒物和臭氧的来源&#xff0c;特别是臭氧的前体物之…

遥测终端助力城市内涝积水监测,守护城市生命线!

近年来&#xff0c;随着全球气候的变化和城市化进程的加速&#xff0c;强降雨事件频发&#xff0c;导致城市内涝问题日益严重。道路低洼处、下穿式立交桥和隧道在强降雨时常常产生大量积水&#xff0c;给人们的出行带来极大不便&#xff0c;严重时甚至威胁人民的生命安全和造成…

Unity 学习笔记索引

Unity安装与简单设置 Unity 常用操作与素材网站 Unity 脚本-生命周期常用函数 Unity 预制体与变体 Unity 使用脚本获取组件&#xff0c;代码生成预制体 Unity 向量计算、欧拉角与四元数转换、输出文本、告警、错误、修改时间、定时器、路径、 Unity 切换场景-&#xff08;同步与…

JVM运行时数据区——方法区

文章目录 1、栈、堆、方法区的交互关系2、方法区的理解2.1、方法区的官方描述2.2、方法区的基本理解2.3、JDK中方法区的变化 3、设置方法区大小与OOM3.1、设置方法区内存的大小3.2、方法区内存溢出 4、方法区的内部结构4.1、类型信息、域信息和方法信息介绍4.1.1、类型信息4.1.…

Spring Cloud原理详解

Spring Cloud 是基于 Spring Boot 的微服务架构开发工具包&#xff0c;旨在帮助开发人员快速构建分布式系统中的一些常见模式&#xff0c;例如配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、领导选举、分布式会话和集群状态。Spring Cloud 是 Spring 生态系…

用户和用户组管理及密码管理

用户&#xff1a; useradd 新建用户 useradd 用户名称 useradd -g 组名称 用户名称 userdel 删除用户 passwd 修改用户密码 usermod 修改用户属性 usermod [选项] 用户名 chage 修改用户属性 chage [选项…

动手学深度学习—循环神经网络RNN详解

循环神经网络 循环神经网络的步骤&#xff1a; 处理数据 将数据按照批量大小和时间步数进行处理&#xff0c;最后得到迭代器&#xff0c;即每一个迭代的大小是批量大小时间步数&#xff0c;迭代次数根据整个数据的大小决定&#xff0c;最后得出处理的数据&#xff08;参照第三…

极狐GitLab Runner 添加 极狐GitLab 域名 host

本文作者 徐晓伟 自定义 GitLab 域名解析 查看极狐 GitLab runner 日志 查看极狐 GitLab Runner Pod 名称 [rootanolis-7-9 ~]# kubectl -n gitlab-test get pod | grep gitlab-runner my-gitlab-gitlab-runner-6fb4bf7468-nmnkp 0/1 Running 29 (62s ago…

【嵌入式——QT】QDockWidget

QDockWidget提供了dock widget的概念&#xff0c;也称为工具面板或实用窗口。Dock窗口是放置在QMainWindow中围绕中心窗口组件的Dock窗口组件区域中的次要窗口&#xff0c;QDockWidget是可以在QMainWindow窗口停靠&#xff0c;或在桌面最上层浮动的界面组件。 停靠窗口可以被移…

重拾前端基础知识:JavaScript

重拾前端基础知识&#xff1a;JavaScript 前言使用JavaScript输出语法运算符条件语句循环数据类型字符串数字数组对象日期函数 数学正则表达式异常处理类集合模块JSON闭包异步调试DOM&#xff08;文档对象模型&#xff09;事件事件监听器表单 BOM&#xff08;浏览器对象模型&am…

【排序】详解选择排序

一、思想 选择排序的原理与思想非常直观和简单&#xff0c;它通过不断地选择未排序部分的最小&#xff08;或最大&#xff09;元素&#xff0c;并将其放到已排序部分的末尾来实现排序。 具体来说&#xff0c;选择排序的过程可以分解为以下几个步骤&#xff1a; 寻找最小&…

三步骤找到用户真正痛点 提高需求分析质量

用户痛点对于需求分析具有至关重要的作用&#xff0c;这直接关系着需求分析结果是否真正满足用户需求&#xff0c;关系着最终研发的产品是否能够满足市场的需求&#xff0c;是否能够在竞争激烈的市场中脱颖而出。因此找到用户真正痛点至关重要。 1、什么是痛点 痛点是消费者心理…

DML相关操作

DML 是数据操作语言&#xff0c;用来对数据库中表的数据记录进行增删改操作 添加数据&#xff08;insert&#xff09;修改数据&#xff08;update&#xff09;删除数据&#xff08;delete&#xff09; DML-添加数据 1.给指定字段添加数据 insert into 表名&#xff08;字段…

关于用强化学习进行股市预测的新思路(2)

据上次新模型开始正式使用以来&#xff0c;发现了几个问题。 1. 因为是一个转债对应一个模型&#xff0c;导致每次预测结果很少。 2. 预测出来的结果&#xff0c;大部分还是受大盘影响。不过大部分最终还是会回本盈利&#xff0c;时间长短的问题。 3. 需要经常更新模型&#x…