usecrate::grapheme::GraphemeClusterSegmenterBorrowed; usecrate::provider::*; use alloc::vec::Vec; use core::char::{decode_utf16, REPLACEMENT_CHARACTER}; use potential_utf::PotentialUtf8; use zerovec::maps::ZeroMapBorrowed;
mod matrix; use matrix::*;
// A word break iterator using LSTM model. Input string have to be same language.
impl<'l, 'data> BiesIterator<'l, 'data> { // input_seq is a sequence of id numbers that represents grapheme clusters or code points in the input line. These ids are used later // in the embedding layer of the model. fn new(segmenter: &'l LstmSegmenter<'data>, input_seq: Vec<u16>) -> Self { let hunits = segmenter.fw_u.dim().1;
// Backward LSTM letmut c_bw = MatrixOwned::<1>::new_zero([hunits]); letmut h_bw = MatrixOwned::<2>::new_zero([input_seq.len(), hunits]); for (i, &g_id) in input_seq.iter().enumerate().rev() { if i + 1 < input_seq.len() {
h_bw.as_mut().copy_submatrix::<1>(i + 1, i);
} #[expect(clippy::unwrap_used)]
compute_hc(
segmenter.embedding.submatrix::<1>(g_id as usize).unwrap(), /* shape (dict.len() + 1, hunit), g_id is at most dict.len() */
h_bw.submatrix_mut(i).unwrap(), // shape (input_seq.len(), hunits)
c_bw.as_mut(),
segmenter.bw_w,
segmenter.bw_u,
segmenter.bw_b,
);
}
impl Iterator for BiesIterator<'_, '_> { type Item = bool;
fn next(&mutself) -> Option<Self::Item> { let (i, g_id) = self.input_seq.next()?;
#[expect(clippy::unwrap_used)]
compute_hc( self.segmenter
.embedding
.submatrix::<1>(g_id as usize)
.unwrap(), // shape (dict.len() + 1, hunit), g_id is at most dict.len() self.curr_fw.as_mut(), self.c_fw.as_mut(), self.segmenter.fw_w, self.segmenter.fw_u, self.segmenter.fw_b,
);
#[expect(clippy::unwrap_used)] // shape (input_seq.len(), hunits) let curr_bw = self.h_bw.submatrix::<1>(i).unwrap(); letmut weights = [0.0; 4]; letmut curr_est = MatrixBorrowedMut {
data: &mut weights,
dims: [4],
};
curr_est.add_dot_2d(self.curr_fw.as_borrowed(), self.segmenter.timew_fw);
curr_est.add_dot_2d(curr_bw, self.segmenter.timew_bw); #[expect(clippy::unwrap_used)] // both shape (4)
curr_est.add(self.segmenter.time_b).unwrap(); // For correct BIES weight calculation we'd now have to apply softmax, however // we're only doing a naive argmax, so a monotonic function doesn't make a difference.
#[expect(clippy::unwrap_used)] // first dimension is 4
s_t.submatrix_mut::<1>(0).unwrap().sigmoid_transform(); #[expect(clippy::unwrap_used)] // first dimension is 4
s_t.submatrix_mut::<1>(1).unwrap().sigmoid_transform(); #[expect(clippy::unwrap_used)] // first dimension is 4
s_t.submatrix_mut::<1>(2).unwrap().tanh_transform(); #[expect(clippy::unwrap_used)] // first dimension is 4
s_t.submatrix_mut::<1>(3).unwrap().sigmoid_transform();
#[expect(clippy::unwrap_used)] // first dimension is 4
c_tm1.convolve(
s_t.as_borrowed().submatrix(0).unwrap(),
s_t.as_borrowed().submatrix(2).unwrap(),
s_t.as_borrowed().submatrix(1).unwrap(),
);
#[expect(clippy::unwrap_used)] // first dimension is 4
h_tm1.mul_tanh(s_t.as_borrowed().submatrix(3).unwrap(), c_tm1.as_borrowed());
}
#[cfg(test)] mod tests { usesuper::*; usecrate::GraphemeClusterSegmenter; use icu_provider::prelude::*; use serde::Deserialize;
/// `TestCase` is a struct used to store a single test case. /// Each test case has two attributes: `unseg` which denotes the unsegmented line, and `true_bies` which indicates the Bies /// sequence representing the true segmentation. #[derive(PartialEq, Debug, Deserialize)] struct TestCase {
unseg: String,
expected_bies: String,
true_bies: String,
}
/// `TestTextData` is a struct to store a vector of `TestCase` that represents a test text. #[derive(PartialEq, Debug, Deserialize)] struct TestTextData {
testcases: Vec<TestCase>,
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.