"R-package/vscode:/vscode.git/clone" did not exist on "9bf1f8076b1495ec4a970e9af17c725d304820dd"
test_basic.R 7.22 KB
Newer Older
1
context("lightgbm()")
Guolin Ke's avatar
Guolin Ke committed
2

3
4
data(agaricus.train, package = "lightgbm")
data(agaricus.test, package = "lightgbm")
Guolin Ke's avatar
Guolin Ke committed
5
6
7
train <- agaricus.train
test <- agaricus.test

8
windows_flag <- grepl("Windows", Sys.info()[["sysname"]])
Guolin Ke's avatar
Guolin Ke committed
9
10

test_that("train and predict binary classification", {
11
  nrounds <- 10L
12
13
14
  bst <- lightgbm(
    data = train$data
    , label = train$label
15
    , num_leaves = 5L
16
17
18
19
    , nrounds = nrounds
    , objective = "binary"
    , metric = "binary_error"
  )
Guolin Ke's avatar
Guolin Ke committed
20
21
22
23
24
  expect_false(is.null(bst$record_evals))
  record_results <- lgb.get.eval.result(bst, "train", "binary_error")
  expect_lt(min(record_results), 0.02)

  pred <- predict(bst, test$data)
25
  expect_equal(length(pred), 1611L)
26

27
28
29
30
  pred1 <- predict(bst, train$data, num_iteration = 1L)
  expect_equal(length(pred1), 6513L)
  err_pred1 <- sum((pred1 > 0.5) != train$label) / length(train$label)
  err_log <- record_results[1L]
Guolin Ke's avatar
Guolin Ke committed
31
32
33
34
35
  expect_lt(abs(err_pred1 - err_log), 10e-6)
})


test_that("train and predict softmax", {
36
  lb <- as.numeric(iris$Species) - 1L
Guolin Ke's avatar
Guolin Ke committed
37

38
  bst <- lightgbm(
39
    data = as.matrix(iris[, -5L])
40
    , label = lb
41
    , num_leaves = 4L
42
    , learning_rate = 0.1
43
44
45
    , nrounds = 20L
    , min_data = 20L
    , min_hess = 20.0
46
47
    , objective = "multiclass"
    , metric = "multi_error"
48
    , num_class = 3L
49
  )
Guolin Ke's avatar
Guolin Ke committed
50
51
52
53
54

  expect_false(is.null(bst$record_evals))
  record_results <- lgb.get.eval.result(bst, "train", "multi_error")
  expect_lt(min(record_results), 0.03)

55
56
  pred <- predict(bst, as.matrix(iris[, -5L]))
  expect_equal(length(pred), nrow(iris) * 3L)
Guolin Ke's avatar
Guolin Ke committed
57
58
59
60
})


test_that("use of multiple eval metrics works", {
61
62
63
  bst <- lightgbm(
    data = train$data
    , label = train$label
64
65
66
    , num_leaves = 4L
    , learning_rate = 1.0
    , nrounds = 10L
67
    , objective = "binary"
68
    , metric = list("binary_error", "auc", "binary_logloss")
69
  )
Guolin Ke's avatar
Guolin Ke committed
70
71
72
  expect_false(is.null(bst$record_evals))
})

73
74
75
76
77
78
79
80
81
82
83
84
85
86
test_that("lightgbm() rejects negative or 0 value passed to nrounds", {
  dtrain <- lgb.Dataset(train$data, label = train$label)
  params <- list(objective = "regression", metric = "l2,l1")
  for (nround_value in c(-10L, 0L)) {
    expect_error({
      bst <- lightgbm(
        data = dtrain
        , params = params
        , nrounds = nround_value
      )
    }, "nrounds should be greater than zero")
  }
})

Guolin Ke's avatar
Guolin Ke committed
87
88

test_that("training continuation works", {
89
  testthat::skip("This test is currently broken. See issue #2468 for details.")
90
91
92
93
94
  dtrain <- lgb.Dataset(
    train$data
    , label = train$label
    , free_raw_data = FALSE
  )
95
  watchlist <- list(train = dtrain)
96
97
98
  param <- list(
    objective = "binary"
    , metric = "binary_logloss"
99
100
    , num_leaves = 5L
    , learning_rate = 1.0
101
  )
Guolin Ke's avatar
Guolin Ke committed
102
103

  # for the reference, use 10 iterations at once:
104
105
  bst <- lgb.train(param, dtrain, nrounds = 10L, watchlist)
  err_bst <- lgb.get.eval.result(bst, "train", "binary_logloss", 10L)
Guolin Ke's avatar
Guolin Ke committed
106
  # first 5 iterations:
107
  bst1 <- lgb.train(param, dtrain, nrounds = 5L, watchlist)
Guolin Ke's avatar
Guolin Ke committed
108
109
110
  # test continuing from a model in file
  lgb.save(bst1, "lightgbm.model")
  # continue for 5 more:
111
112
  bst2 <- lgb.train(param, dtrain, nrounds = 5L, watchlist, init_model = bst1)
  err_bst2 <- lgb.get.eval.result(bst2, "train", "binary_logloss", 10L)
Guolin Ke's avatar
Guolin Ke committed
113
114
  expect_lt(abs(err_bst - err_bst2), 0.01)

115
116
  bst2 <- lgb.train(param, dtrain, nrounds = 5L, watchlist, init_model = "lightgbm.model")
  err_bst2 <- lgb.get.eval.result(bst2, "train", "binary_logloss", 10L)
Guolin Ke's avatar
Guolin Ke committed
117
118
119
  expect_lt(abs(err_bst - err_bst2), 0.01)
})

120
context("lgb.cv()")
Guolin Ke's avatar
Guolin Ke committed
121
122

test_that("cv works", {
123
124
125
126
127
  dtrain <- lgb.Dataset(train$data, label = train$label)
  params <- list(objective = "regression", metric = "l2,l1")
  bst <- lgb.cv(
    params
    , dtrain
128
129
130
131
132
    , 10L
    , nfold = 5L
    , min_data = 1L
    , learning_rate = 1.0
    , early_stopping_rounds = 10L
133
  )
Guolin Ke's avatar
Guolin Ke committed
134
135
  expect_false(is.null(bst$record_evals))
})
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

test_that("lgb.cv() rejects negative or 0 value passed to nrounds", {
  dtrain <- lgb.Dataset(train$data, label = train$label)
  params <- list(objective = "regression", metric = "l2,l1")
  for (nround_value in c(-10L, 0L)) {
    expect_error({
      bst <- lgb.cv(
        params
        , dtrain
        , nround_value
        , nfold = 5L
        , min_data = 1L
      )
    }, "nrounds should be greater than zero")
  }
})

test_that("lgb.cv() throws an informative error is 'data' is not an lgb.Dataset and labels are not given", {
  bad_values <- list(
    4L
    , "hello"
    , list(a = TRUE, b = seq_len(10L))
    , data.frame(x = seq_len(5L), y = seq_len(5L))
    , data.table::data.table(x = seq_len(5L),  y = seq_len(5L))
    , matrix(data = seq_len(10L), 2L, 5L)
  )
  for (val in bad_values) {
    expect_error({
      bst <- lgb.cv(
        params = list(objective = "regression", metric = "l2,l1")
        , data = val
        , 10L
        , nfold = 5L
        , min_data = 1L
      )
    }, regexp = "'label' must be provided for lgb.cv if 'data' is not an 'lgb.Dataset'", fixed = TRUE)
  }
})

context("lgb.train()")

test_that("lgb.train() rejects negative or 0 value passed to nrounds", {
  dtrain <- lgb.Dataset(train$data, label = train$label)
  params <- list(objective = "regression", metric = "l2,l1")
  for (nround_value in c(-10L, 0L)) {
    expect_error({
      bst <- lgb.train(
        params
        , dtrain
        , nround_value
      )
    }, "nrounds should be greater than zero")
  }
})

test_that("lgb.train() throws an informative error if 'data' is not an lgb.Dataset", {
  bad_values <- list(
    4L
    , "hello"
    , list(a = TRUE, b = seq_len(10L))
    , data.frame(x = seq_len(5L), y = seq_len(5L))
    , data.table::data.table(x = seq_len(5L),  y = seq_len(5L))
    , matrix(data = seq_len(10L), 2L, 5L)
  )
  for (val in bad_values) {
    expect_error({
      bst <- lgb.train(
        params = list(objective = "regression", metric = "l2,l1")
        , data = val
        , 10L
      )
    }, regexp = "data must be an lgb.Dataset instance", fixed = TRUE)
  }
})

test_that("lgb.train() throws an informative error if 'valids' is not a list of lgb.Dataset objects", {
  valids <- list(
    "valid1" = data.frame(x = rnorm(5L), y = rnorm(5L))
    , "valid2" = data.frame(x = rnorm(5L), y = rnorm(5L))
  )
  expect_error({
    bst <- lgb.train(
      params = list(objective = "regression", metric = "l2,l1")
      , data = lgb.Dataset(train$data, label = train$label)
      , 10L
      , valids = valids
    )
  }, regexp = "valids must be a list of lgb.Dataset elements")
})

test_that("lgb.train() errors if 'valids' is a list of lgb.Dataset objects but some do not have names", {
  valids <- list(
    "valid1" = lgb.Dataset(matrix(rnorm(10L), 5L, 2L))
    , lgb.Dataset(matrix(rnorm(10L), 2L, 5L))
  )
  expect_error({
    bst <- lgb.train(
      params = list(objective = "regression", metric = "l2,l1")
      , data = lgb.Dataset(train$data, label = train$label)
      , 10L
      , valids = valids
    )
  }, regexp = "each element of valids must have a name")
})

test_that("lgb.train() throws an informative error if 'valids' contains lgb.Dataset objects but none have names", {
  valids <- list(
    lgb.Dataset(matrix(rnorm(10L), 5L, 2L))
    , lgb.Dataset(matrix(rnorm(10L), 2L, 5L))
  )
  expect_error({
    bst <- lgb.train(
      params = list(objective = "regression", metric = "l2,l1")
      , data = lgb.Dataset(train$data, label = train$label)
      , 10L
      , valids = valids
    )
  }, regexp = "each element of valids must have a name")
})