Cảnh giác sample
với việc chia tách nếu bạn tìm kiếm kết quả có thể lặp lại. Nếu dữ liệu của bạn thay đổi thậm chí một chút, sự phân chia sẽ thay đổi ngay cả khi bạn sử dụngset.seed
. Ví dụ: hãy tưởng tượng danh sách ID được sắp xếp trong dữ liệu của bạn là tất cả các số trong khoảng từ 1 đến 10. Nếu bạn chỉ bỏ một quan sát, giả sử 4, lấy mẫu theo vị trí sẽ mang lại kết quả khác nhau vì hiện tại 5 đến 10 địa điểm đã di chuyển.
Một phương pháp khác là sử dụng hàm băm để ánh xạ ID thành một số số ngẫu nhiên giả và sau đó lấy mẫu trên mod của những số này. Mẫu này ổn định hơn vì sự phân công hiện được xác định bởi hàm băm của mỗi quan sát chứ không phải bởi vị trí tương đối của nó.
Ví dụ:
require(openssl) # for md5
require(data.table) # for the demo data
set.seed(1) # this won't help `sample`
population <- as.character(1e5:(1e6-1)) # some made up ID names
N <- 1e4 # sample size
sample1 <- data.table(id = sort(sample(population, N))) # randomly sample N ids
sample2 <- sample1[-sample(N, 1)] # randomly drop one observation from sample1
# samples are all but identical
sample1
sample2
nrow(merge(sample1, sample2))
[1] 9999
# row splitting yields very different test sets, even though we've set the seed
test <- sample(N-1, N/2, replace = F)
test1 <- sample1[test, .(id)]
test2 <- sample2[test, .(id)]
nrow(test1)
[1] 5000
nrow(merge(test1, test2))
[1] 2653
# to fix that, we can use some hash function to sample on the last digit
md5_bit_mod <- function(x, m = 2L) {
# Inputs:
# x: a character vector of ids
# m: the modulo divisor (modify for split proportions other than 50:50)
# Output: remainders from dividing the first digit of the md5 hash of x by m
as.integer(as.hexmode(substr(openssl::md5(x), 1, 1)) %% m)
}
# hash splitting preserves the similarity, because the assignment of test/train
# is determined by the hash of each obs., and not by its relative location in the data
# which may change
test1a <- sample1[md5_bit_mod(id) == 0L, .(id)]
test2a <- sample2[md5_bit_mod(id) == 0L, .(id)]
nrow(merge(test1a, test2a))
[1] 5057
nrow(test1a)
[1] 5057
cỡ mẫu không chính xác 5000 vì sự phân công là xác suất, nhưng nó không phải là vấn đề trong các mẫu lớn nhờ vào luật số lượng lớn.
Xem thêm: http://blog.richardweiss.org/2016/12/25/hash-splits.html
và /crypto/20742/statistic-properies-of-hash-fifts-when tính toán-modulo
x
có thể là chỉ số (hàng / col nos. say) của bạndata
.size
có thể0.75*nrow(data)
. Hãy thửsample(1:10, 4, replace = FALSE, prob = NULL)
xem những gì nó làm.