use super::*;
#[test]
fn a_row_mixing_recognized_and_unrecognized_words_uses_both_index_paths() {
let vocab = vocab(&["cat"]);
let stopwords = stopwords(&[]);
let tokens = token_text(&["[CLS]", "cat", "xyzzy", "[SEP]"]);
let matrix = Tensor::from_vec(
vec![
0f32, 0., 0., 0., 0., 0., 0., 0., 1.0, 0., 0., 0., 0., 0., 0., 0.,
],
(2, 2, 4),
&Device::Cpu,
)
.unwrap();
let hidden_row = vec![
vec![0.0f32, 0.0],
vec![1.0, 0.0],
vec![0.0, 0.0],
vec![0.0, 0.0],
];
let embedding = pooling::pool_row(
&hidden_row,
&[0, 1, 2, 3],
&tokens,
&vocab,
&stopwords,
&matrix,
false,
)
.unwrap();
let tf = 1.0 * (1.2 + 1.0) / (1.0 + 1.2 * (1.0 - 0.75 + 0.75 * 2.0 / 150.0));
let dense = index::dense_index(1, 0);
let hashed = index::hashed_index("xyzzy");
assert!(dense < 128_000, "{dense}");
assert!(hashed >= 128_000, "{hashed}");
assert_eq!(embedding.indices, vec![dense, hashed]);
for &got in &embedding.values {
assert!((got - tf).abs() < 1e-5, "{got} vs {tf}");
}
}
#[test]
fn a_row_of_only_unrecognized_words_produces_only_hashed_entries() {
let vocab = vocab(&["cat"]);
let stopwords = stopwords(&[]);
let tokens = token_text(&["foo", "bar"]);
let matrix = Tensor::from_vec(vec![0f32; 16], (2, 2, 4), &Device::Cpu).unwrap();
let hidden_row = vec![vec![0.0f32, 0.0], vec![0.0, 0.0]];
let embedding = pooling::pool_row(
&hidden_row,
&[0, 1],
&tokens,
&vocab,
&stopwords,
&matrix,
false,
)
.unwrap();
let tf = 1.0 * (1.2 + 1.0) / (1.0 + 1.2 * (1.0 - 0.75 + 0.75 * 2.0 / 150.0));
let mut expected = [index::hashed_index("foo"), index::hashed_index("bar")];
expected.sort_unstable();
assert_eq!(embedding.indices, expected);
assert!(
embedding.indices.iter().all(|&i| i >= 128_000),
"{:?}",
embedding.indices
);
for &got in &embedding.values {
assert!((got - tf).abs() < 1e-5, "{got} vs {tf}");
}
}
#[test]
fn a_bare_punctuation_token_never_moves_a_recognized_words_own_weight() {
let vocab = vocab(&["cat"]);
let stopwords = stopwords(&[]);
let matrix = Tensor::from_vec(
vec![
0f32, 0., 0., 0., 0., 0., 0., 0., 1.0, 0., 0., 0., 0., 0., 0., 0.,
],
(2, 2, 4),
&Device::Cpu,
)
.unwrap();
let control_tokens = token_text(&["[CLS]", "cat", "[SEP]"]);
let control_hidden = vec![vec![0.0f32, 0.0], vec![1.0, 0.0], vec![0.0, 0.0]];
let control = pooling::pool_row(
&control_hidden,
&[0, 1, 2],
&control_tokens,
&vocab,
&stopwords,
&matrix,
false,
)
.unwrap();
let punctuated_tokens = token_text(&["[CLS]", "cat", ".", "[SEP]"]);
let punctuated_hidden = vec![
vec![0.0f32, 0.0],
vec![1.0, 0.0],
vec![0.0, 0.0],
vec![0.0, 0.0],
];
let punctuated = pooling::pool_row(
&punctuated_hidden,
&[0, 1, 2, 3],
&punctuated_tokens,
&vocab,
&stopwords,
&matrix,
false,
)
.unwrap();
assert_eq!(
control.indices,
vec![index::dense_index(1, 0)],
"control row (no punctuation)"
);
assert_eq!(
punctuated.values[0], control.values[0],
"\"cat\"'s own weight must not move just because the row also contains a bare \".\""
);
assert_eq!(
punctuated.indices, control.indices,
"a correctly filtered punctuation token must add no index of its own"
);
let tf = 1.0 * (1.2 + 1.0) / (1.0 + 1.2 * (1.0 - 0.75 + 0.75 * 1.0 / 150.0));
assert!(
(control.values[0] - tf).abs() < 1e-5,
"{} vs {tf}",
control.values[0]
);
}
#[test]
fn an_empty_row_produces_an_empty_embedding() {
let vocab = vocab(&["cat"]);
let stopwords = stopwords(&[]);
let tokens = token_text(&["cat"]);
let matrix = Tensor::from_vec(vec![0f32; 16], (2, 2, 4), &Device::Cpu).unwrap();
let hidden_row: Vec<Vec<f32>> = vec![];
let embedding = pooling::pool_row(
&hidden_row,
&[],
&tokens,
&vocab,
&stopwords,
&matrix,
false,
)
.unwrap();
assert!(embedding.is_empty());
}