extern crate chobitlibs; use chobitlibs::chobit_ai::*; use chobitlibs::chobit_rand::*; use std::mem::size_of; #[inline] fn rand_num(rng: &mut ChobitRand) -> f32 { ((rng.next_f64() * 2.0) - 1.0) as f32 } #[test] fn to_from_label_test() { const COUNT: usize = 100; let mut rng = ChobitRand::new("to_from_label_test".as_bytes()); macro_rules! to_from_label_test_core { ($type:ty, $rng:expr, $to_func:ident, $from_func:ident) => {{ let mut vec = MathVec::<{size_of::<$type>() * 8}>::new(); let label = rng.next_u64() as $type; vec.$from_func(label); let label_2 = vec.$to_func(); assert_eq!(label, label_2, "{:0128b} \n {:0128b}", label, label_2); }}; (u128, $rng:expr, $to_func:ident, $from_func:ident) => {{ let mut vec = MathVec::<{size_of::<$type>() * 8}>::new(); let label = ((rng.next_u64() as u128) << 64) | (rng.next_u64() as u128); vec.$from_func(label); let label_2 = vec.$to_func(); assert_eq!(label, label_2, "{:0128b} \n {:0128b}", label, label_2); }}; } for _ in 0..COUNT { to_from_label_test_core!(u8, rng, to_u8_label, load_u8_label); to_from_label_test_core!(u16, rng, to_u16_label, load_u16_label); to_from_label_test_core!(u32, rng, to_u32_label, load_u32_label); to_from_label_test_core!(u64, rng, to_u64_label, load_u64_label); to_from_label_test_core!(u128, rng, to_u128_label, load_u128_label); } } fn rand_math_vec(rng: &mut ChobitRand, vec: &mut MathVec) { vec.iter_mut().for_each(|val| {*val = rand_num(rng)}); } #[test] fn math_vec_test_1() { { let mut vec_1 = MathVec::<10>::new(); vec_1.as_mut_array().iter_mut().for_each(|x| {*x = 1.0;}); let mut vec_2 = MathVec::<10>::new(); vec_2.as_mut_array().iter_mut().for_each(|x| {*x = 2.0;}); let mut vec_3 = MathVec::<10>::new(); vec_3.as_mut_array().iter_mut().for_each(|x| {*x = 3.0;}); let vec_4 = &vec_1 + &vec_2; assert_eq!(vec_3, vec_4); vec_1 += &vec_2; assert_eq!(vec_1, vec_4); } { let mut vec_1 = MathVec::<10>::new(); vec_1.as_mut_array().iter_mut().for_each(|x| {*x = 3.0;}); let mut vec_2 = MathVec::<10>::new(); vec_2.as_mut_array().iter_mut().for_each(|x| {*x = 1.0;}); let mut vec_3 = MathVec::<10>::new(); vec_3.as_mut_array().iter_mut().for_each(|x| {*x = 2.0;}); let vec_4 = &vec_1 - &vec_2; assert_eq!(vec_3, vec_4); vec_1 -= &vec_2; assert_eq!(vec_1, vec_4); } } #[test] fn math_vec_test_2() { { let mut vec_1 = MathVec::<10>::new(); vec_1.as_mut_array().iter_mut().for_each(|x| {*x = 2.0;}); let scalar: f32 = 3.0; let mut vec_2 = MathVec::<10>::new(); vec_2.as_mut_array().iter_mut().for_each(|x| {*x = 6.0;}); let vec_3 = &vec_1 * scalar; assert_eq!(vec_3, vec_2); vec_1 *= scalar; assert_eq!(vec_1, vec_2); } { let mut vec_1 = MathVec::<10>::new(); vec_1.as_mut_array().iter_mut().for_each(|x| {*x = 6.0;}); let scalar: f32 = 3.0; let mut vec_2 = MathVec::<10>::new(); vec_2.as_mut_array().iter_mut().for_each(|x| {*x = 2.0;}); let vec_3 = &vec_1 / scalar; assert_eq!(vec_3, vec_2); vec_1 /= scalar; assert_eq!(vec_1, vec_2); } { let mut vec_1 = MathVec::<10>::new(); vec_1.as_mut_array().iter_mut().for_each(|x| {*x = 12.0;}); let scalar: f32 = 10.0; let mut vec_2 = MathVec::<10>::new(); vec_2.as_mut_array().iter_mut().for_each(|x| {*x = 2.0;}); let vec_3 = &vec_1 % scalar; assert_eq!(vec_3, vec_2); vec_1 %= scalar; assert_eq!(vec_1, vec_2); } } #[test] fn math_vec_test_3() { { let mut vec_1 = MathVec::<10>::new(); vec_1.as_mut_array().iter_mut().for_each(|x| {*x = 2.0;}); let mut vec_2 = MathVec::<10>::new(); vec_2.as_mut_array().iter_mut().for_each(|x| {*x = 3.0;}); let scalar_1: f32 = 2.0 * 3.0 * 10.0; let scalar_2 = &vec_1 * &vec_2; assert_eq!(scalar_2, scalar_1); } } #[test] fn math_vec_test_4() { { let mut vec_1 = MathVec::<10>::new(); vec_1.as_mut_array().iter_mut().for_each(|x| {*x = 2.0;}); let mut vec_2 = MathVec::<10>::new(); vec_2.as_mut_array().iter_mut().for_each(|x| {*x = 3.0;}); let mut vec_3 = MathVec::<10>::new(); vec_3.as_mut_array().iter_mut().for_each(|x| {*x = 6.0;}); let vec_4 = vec_1.pointwise_mul(&vec_2); assert_eq!(vec_4, vec_3); vec_1.pointwise_mul_assign(&vec_2); assert_eq!(vec_1, vec_3); } { let mut vec_1 = MathVec::<10>::new(); vec_1.as_mut_array().iter_mut().for_each(|x| {*x = 6.0;}); let mut vec_2 = MathVec::<10>::new(); vec_2.as_mut_array().iter_mut().for_each(|x| {*x = 3.0;}); let mut vec_3 = MathVec::<10>::new(); vec_3.as_mut_array().iter_mut().for_each(|x| {*x = 2.0;}); let vec_4 = vec_1.pointwise_div(&vec_2); assert_eq!(vec_4, vec_3); vec_1.pointwise_div_assign(&vec_2); assert_eq!(vec_1, vec_3); } { let mut vec_1 = MathVec::<10>::new(); vec_1.as_mut_array().iter_mut().for_each(|x| {*x = 12.0;}); let mut vec_2 = MathVec::<10>::new(); vec_2.as_mut_array().iter_mut().for_each(|x| {*x = 10.0;}); let mut vec_3 = MathVec::<10>::new(); vec_3.as_mut_array().iter_mut().for_each(|x| {*x = 2.0;}); let vec_4 = vec_1.pointwise_rem(&vec_2); assert_eq!(vec_4, vec_3); vec_1.pointwise_rem_assign(&vec_2); assert_eq!(vec_1, vec_3); } } #[test] fn math_vec_test_5() { { let mut vec_1 = MathVec::<10>::new(); vec_1.as_mut_array().iter_mut().for_each(|x| {*x = 1.0;}); let mut vec_2 = MathVec::<10>::new(); vec_2.as_mut_array().iter_mut().for_each(|x| {*x = 2.0;}); vec_1.copy_from(&vec_2); assert_eq!(vec_1, vec_2); } } fn rand_weights( rng: &mut ChobitRand, weights: &mut Weights ) { weights.iter_mut().for_each(|val| {*val = rand_num(rng)}); } #[test] fn weights_test_1() { const OUT: usize = 7; const IN: usize = 13; const BIAS_LEN: usize = OUT; const INPUT_WEIGHTS_LEN: usize = OUT * IN; const STATE_WEIGHTS_LEN: usize = OUT * OUT; const LENGTH: usize = BIAS_LEN + INPUT_WEIGHTS_LEN + STATE_WEIGHTS_LEN; { let mut weights = Weights::::new(true); assert_eq!(weights.as_slice().len(), LENGTH); assert_eq!(weights.as_mut_slice().len(), LENGTH); let len_b_1 = weights.bias().len(); let len_b_2 = weights.bias_mut().len(); assert_eq!(len_b_1, BIAS_LEN); assert_eq!(len_b_2, BIAS_LEN); let len_i_1 = weights.input_weights().len(); let len_i_2 = weights.input_weights_mut().len(); assert_eq!(len_i_1, OUT); assert_eq!(len_i_2, OUT); let len_i_1 = len_i_1 * weights.input_weights()[0].len(); let len_i_2 = len_i_2 * weights.input_weights_mut()[0].len(); assert_eq!(len_i_1, INPUT_WEIGHTS_LEN); assert_eq!(len_i_2, INPUT_WEIGHTS_LEN); let len_s_1 = weights.state_weights().unwrap().len(); let len_s_2 = weights.state_weights_mut().unwrap().len(); assert_eq!(len_s_1, OUT); assert_eq!(len_s_2, OUT); let len_s_1 = len_s_1 * weights.state_weights().unwrap()[0].len(); let len_s_2 = len_s_2 * weights.state_weights_mut().unwrap()[0].len(); assert_eq!(len_s_1, STATE_WEIGHTS_LEN); assert_eq!(len_s_2, STATE_WEIGHTS_LEN); assert_eq!(len_b_1 + len_i_1 + len_s_1, LENGTH); assert_eq!(len_b_2 + len_i_2 + len_s_2, LENGTH); } { let mut weights = Weights::::new(true); let ptr_1 = weights.bias().as_ptr(); let ptr_2 = weights.bias_mut().as_ptr(); assert_eq!(ptr_1, ptr_2); let ptr_1 = weights.input_weights().as_ptr(); let ptr_2 = weights.input_weights_mut().as_ptr(); assert_eq!(ptr_1, ptr_2); let ptr_1 = weights.state_weights().unwrap().as_ptr(); let ptr_2 = weights.state_weights_mut().unwrap().as_ptr(); assert_eq!(ptr_1, ptr_2); } { let weights = Weights::::new(true); let whole = weights.as_slice(); let bias = weights.bias(); let input_weights = weights.input_weights(); let state_weights = weights.state_weights().unwrap(); let whole_ptr = whole.as_ptr(); let bias_ptr = bias.as_ptr(); let input_weights_ptr = input_weights.as_ptr() as *const f32; let state_weights_ptr = state_weights.as_ptr() as *const f32; assert_eq!(whole_ptr, bias_ptr); assert_eq!(unsafe {whole_ptr.add(BIAS_LEN)}, input_weights_ptr); assert_eq!(unsafe {bias_ptr.add(BIAS_LEN)}, input_weights_ptr); assert_eq!( unsafe {whole_ptr.add(BIAS_LEN + INPUT_WEIGHTS_LEN)}, state_weights_ptr ); assert_eq!( unsafe {input_weights_ptr.add(INPUT_WEIGHTS_LEN)}, state_weights_ptr ); assert_eq!( unsafe {whole_ptr.add(LENGTH)}, unsafe {state_weights_ptr.add(STATE_WEIGHTS_LEN)} ); let weights_2 = weights.clone(); let whole_2 = weights_2.as_slice(); assert_eq!(whole_2, whole); assert!( if (whole_2.as_ptr() as usize) < (whole.as_ptr() as usize) { unsafe { (whole_2.as_ptr().add(LENGTH) as usize) < (whole.as_ptr() as usize) } } else if (whole_2.as_ptr() as usize) > (whole.as_ptr() as usize) { unsafe { (whole.as_ptr().add(LENGTH) as usize) < (whole_2.as_ptr() as usize) } } else { false } ); } { let weights = Weights::::new(true); let weights_2 = weights.clone(); let whole = weights_2.as_slice(); let bias = weights_2.bias(); let input_weights = weights_2.input_weights(); let state_weights = weights_2.state_weights().unwrap(); let whole_ptr = whole.as_ptr(); let bias_ptr = bias.as_ptr(); let input_weights_ptr = input_weights.as_ptr() as *const f32; let state_weights_ptr = state_weights.as_ptr() as *const f32; assert_eq!(whole_ptr, bias_ptr); assert_eq!(unsafe {whole_ptr.add(BIAS_LEN)}, input_weights_ptr); assert_eq!(unsafe {bias_ptr.add(BIAS_LEN)}, input_weights_ptr); assert_eq!( unsafe {whole_ptr.add(BIAS_LEN + INPUT_WEIGHTS_LEN)}, state_weights_ptr ); assert_eq!( unsafe {input_weights_ptr.add(INPUT_WEIGHTS_LEN)}, state_weights_ptr ); assert_eq!( unsafe {whole_ptr.add(LENGTH)}, unsafe {state_weights_ptr.add(STATE_WEIGHTS_LEN)} ); } } #[test] fn weights_test_2() { const OUT: usize = 7; const IN: usize = 13; const BIAS_LEN: usize = OUT; const INPUT_WEIGHTS_LEN: usize = OUT * IN; const LENGTH: usize = BIAS_LEN + INPUT_WEIGHTS_LEN; { let mut weights = Weights::::new(false); assert_eq!(weights.as_slice().len(), LENGTH); assert_eq!(weights.as_mut_slice().len(), LENGTH); let len_b_1 = weights.bias().len(); let len_b_2 = weights.bias_mut().len(); assert_eq!(len_b_1, BIAS_LEN); assert_eq!(len_b_2, BIAS_LEN); let len_i_1 = weights.input_weights().len(); let len_i_2 = weights.input_weights_mut().len(); assert_eq!(len_i_1, OUT); assert_eq!(len_i_2, OUT); let len_i_1 = len_i_1 * weights.input_weights()[0].len(); let len_i_2 = len_i_2 * weights.input_weights_mut()[0].len(); assert_eq!(len_i_1, INPUT_WEIGHTS_LEN); assert_eq!(len_i_2, INPUT_WEIGHTS_LEN); assert!(weights.state_weights().is_none()); assert!(weights.state_weights_mut().is_none()); assert_eq!(len_b_1 + len_i_1, LENGTH); assert_eq!(len_b_2 + len_i_2, LENGTH); } { let mut weights = Weights::::new(false); let ptr_1 = weights.bias().as_ptr(); let ptr_2 = weights.bias_mut().as_ptr(); assert_eq!(ptr_1, ptr_2); let ptr_1 = weights.input_weights().as_ptr(); let ptr_2 = weights.input_weights_mut().as_ptr(); assert_eq!(ptr_1, ptr_2); } { let weights = Weights::::new(false); let whole = weights.as_slice(); let bias = weights.bias(); let input_weights = weights.input_weights(); let whole_ptr = whole.as_ptr(); let bias_ptr = bias.as_ptr(); let input_weights_ptr = input_weights.as_ptr() as *const f32; assert_eq!(whole_ptr, bias_ptr); assert_eq!(unsafe {whole_ptr.add(BIAS_LEN)}, input_weights_ptr); assert_eq!(unsafe {bias_ptr.add(BIAS_LEN)}, input_weights_ptr); assert_eq!( unsafe {whole_ptr.add(LENGTH)}, unsafe {input_weights_ptr.add(INPUT_WEIGHTS_LEN)} ); let weights_2 = weights.clone(); let whole_2 = weights_2.as_slice(); assert_eq!(whole_2, whole); assert!( if (whole_2.as_ptr() as usize) < (whole.as_ptr() as usize) { unsafe { (whole_2.as_ptr().add(LENGTH) as usize) < (whole.as_ptr() as usize) } } else if (whole_2.as_ptr() as usize) > (whole.as_ptr() as usize) { unsafe { (whole.as_ptr().add(LENGTH) as usize) < (whole_2.as_ptr() as usize) } } else { false } ); } { let weights = Weights::::new(false); let weights_2 = weights.clone(); let whole = weights_2.as_slice(); let bias = weights_2.bias(); let input_weights = weights_2.input_weights(); let whole_ptr = whole.as_ptr(); let bias_ptr = bias.as_ptr(); let input_weights_ptr = input_weights.as_ptr() as *const f32; assert_eq!(whole_ptr, bias_ptr); assert_eq!(unsafe {whole_ptr.add(BIAS_LEN)}, input_weights_ptr); assert_eq!(unsafe {bias_ptr.add(BIAS_LEN)}, input_weights_ptr); } } #[test] fn weights_test_3() { const OUT: usize = 7; const IN: usize = 13; const WEIGHT_B: f32 = 1.0; const WEIGHT_I: f32 = 2.0; const WEIGHT_S: f32 = 3.0; let mut weights = Weights::::new(true); weights.bias_mut().iter_mut().for_each(|val| {*val = WEIGHT_B;}); let mut weight = WEIGHT_I; for weights in weights.input_weights_mut() { weights.iter_mut().for_each(|val| {*val = weight;}); weight += 0.1; } let mut weight = WEIGHT_S; for weights in weights.state_weights_mut().unwrap() { weights.iter_mut().for_each(|val| {*val = weight;}); weight += 0.1; } const VALUE_I: f32 = 5.0; const VALUE_S: f32 = 7.0; let mut input = MathVec::::new(); input.iter_mut().for_each(|val| {*val = VALUE_I;}); let mut state = MathVec::::new(); state.iter_mut().for_each(|val| {*val = VALUE_S;}); let mut output = MathVec::::new(); weights.calc(&input, Some(&state), &mut output); let mut weight_i = WEIGHT_I; let mut weight_s = WEIGHT_S; for output_val in output.as_array() { let output_val = ((*output_val) * 10.0).round(); let val_i = weight_i * VALUE_I * (IN as f32); let val_s = weight_s * VALUE_S * (OUT as f32); let val = val_i + val_s + WEIGHT_B; let val = (val * 10.0).round(); assert_eq!(output_val, val); weight_i += 0.1; weight_s += 0.1; } } #[test] fn weights_test_4() { const OUT: usize = 7; const IN: usize = 13; const WEIGHT_B: f32 = 1.0; const WEIGHT_I: f32 = 2.0; let mut weights = Weights::::new(false); weights.bias_mut().iter_mut().for_each(|val| {*val = WEIGHT_B;}); let mut weight = WEIGHT_I; for weights in weights.input_weights_mut() { weights.iter_mut().for_each(|val| {*val = weight;}); weight += 0.1; } const VALUE_I: f32 = 5.0; const VALUE_S: f32 = 7.0; let mut input = MathVec::::new(); input.iter_mut().for_each(|val| {*val = VALUE_I;}); let mut state = MathVec::::new(); state.iter_mut().for_each(|val| {*val = VALUE_S;}); let mut output = MathVec::::new(); weights.calc(&input, Some(&state), &mut output); let mut weight_i = WEIGHT_I; for output_val in output.as_array() { let output_val = ((*output_val) * 10.0).round(); let val_i = weight_i * VALUE_I * (IN as f32); let val = val_i + WEIGHT_B; let val = (val * 10.0).round(); assert_eq!(output_val, val); weight_i += 0.1; } } #[test] fn weights_test_5() { const OUT: usize = 7; const IN: usize = 13; const WEIGHT_B: f32 = 1.0; const WEIGHT_I: f32 = 2.0; const WEIGHT_S: f32 = 3.0; let mut weights = Weights::::new(true); weights.bias_mut().iter_mut().for_each(|val| {*val = WEIGHT_B;}); let mut weight = WEIGHT_I; for weights in weights.input_weights_mut() { weights.iter_mut().for_each(|val| {*val = weight;}); weight += 0.1; } let mut weight = WEIGHT_S; for weights in weights.state_weights_mut().unwrap() { weights.iter_mut().for_each(|val| {*val = weight;}); weight += 0.1; } const VALUE_I: f32 = 5.0; const VALUE_S: f32 = 7.0; let mut input = MathVec::::new(); input.iter_mut().for_each(|val| {*val = VALUE_I;}); let mut state = MathVec::::new(); state.iter_mut().for_each(|val| {*val = VALUE_S;}); let mut feedback = MathVec::::new(); let mut v: f32 = 1.0; for feedback_val in feedback.as_mut_array() { *feedback_val = v; v += 1.0; } { let mut grad = MathVec::::new(); weights.grad_with_input(&feedback, &mut grad); for i in 0..grad.len() { let mut check: f32 = 0.0; for j in 0..feedback.len() { check += feedback[j] * weights.input_weights()[j][i]; } assert_eq!( (grad[i] * 10.0).round(), (check * 10.0).round() ); } } { let mut grad = MathVec::::new(); weights.grad_with_state(&feedback, &mut grad); for i in 0..grad.len() { let mut check: f32 = 0.0; for j in 0..feedback.len() { check += feedback[j] * weights.state_weights().unwrap()[j][i]; } assert_eq!( (grad[i] * 10.0).round(), (check * 10.0).round() ); } } { let mut grad = Weights::::new(true); Weights::grad_with_weights(&feedback, &input, Some(&state), &mut grad); assert_eq!(grad.bias(), feedback.as_array()); for i in 0..OUT { for j in 0..IN { let check = feedback[i] * input[j]; assert_eq!( (grad.input_weights()[i][j] * 10.0).round(), (check * 10.0).round() ); } } for i in 0..OUT { for j in 0..OUT { let check = feedback[i] * state[j]; assert_eq!( (grad.state_weights().unwrap()[i][j] * 10.0).round(), (check * 10.0).round() ); } } } } #[test] fn weights_test_6() { const OUT: usize = 7; const IN: usize = 13; const WEIGHT_B: f32 = 1.0; const WEIGHT_I: f32 = 2.0; let mut weights = Weights::::new(false); weights.bias_mut().iter_mut().for_each(|val| {*val = WEIGHT_B;}); let mut weight = WEIGHT_I; for weights in weights.input_weights_mut() { weights.iter_mut().for_each(|val| {*val = weight;}); weight += 0.1; } const VALUE_I: f32 = 5.0; const VALUE_S: f32 = 7.0; let mut input = MathVec::::new(); input.iter_mut().for_each(|val| {*val = VALUE_I;}); let mut state = MathVec::::new(); state.iter_mut().for_each(|val| {*val = VALUE_S;}); let mut feedback = MathVec::::new(); let mut v: f32 = 1.0; for feedback_val in feedback.as_mut_array() { *feedback_val = v; v += 1.0; } { let mut grad = MathVec::::new(); weights.grad_with_input(&feedback, &mut grad); for i in 0..grad.len() { let mut check: f32 = 0.0; for j in 0..feedback.len() { check += feedback[j] * weights.input_weights()[j][i]; } assert_eq!( (grad[i] * 10.0).round(), (check * 10.0).round() ); } } { let mut grad = MathVec::::new(); weights.grad_with_state(&feedback, &mut grad); grad.iter().for_each(|val| {assert_eq!(*val, 0.0)}); } { let mut grad = Weights::::new(false); Weights::grad_with_weights(&feedback, &input, Some(&state), &mut grad); assert_eq!(grad.bias(), feedback.as_array()); for i in 0..OUT { for j in 0..IN { let check = feedback[i] * input[j]; assert_eq!( (grad.input_weights()[i][j] * 10.0).round(), (check * 10.0).round() ); } } } } #[test] fn weights_test_9() { const OUT: usize = 7; const IN: usize = 13; let mut rng = ChobitRand::new("weights_test_9".as_bytes()); { let mut weights_1 = Weights::::new(true); rand_weights(&mut rng, &mut weights_1); let mut weights_2 = Weights::::new(true); rand_weights(&mut rng, &mut weights_2); assert_ne!(weights_1, weights_2); weights_1.copy_from(&weights_2); assert_eq!(weights_1, weights_2); } { let mut weights_1 = Weights::::new(false); rand_weights(&mut rng, &mut weights_1); let mut weights_2 = Weights::::new(false); rand_weights(&mut rng, &mut weights_2); assert_ne!(weights_1, weights_2); weights_1.copy_from(&weights_2); assert_eq!(weights_1, weights_2); } { let mut weights_1 = Weights::::new(true); rand_weights(&mut rng, &mut weights_1); let mut weights_2 = Weights::::new(false); rand_weights(&mut rng, &mut weights_2); assert_ne!(weights_1, weights_2); weights_1.copy_from(&weights_2); assert_ne!(weights_1, weights_2); assert_eq!(&weights_1[..weights_2.len()], weights_2.as_slice()); } { let mut weights_1 = Weights::::new(false); rand_weights(&mut rng, &mut weights_1); let mut weights_2 = Weights::::new(true); rand_weights(&mut rng, &mut weights_2); assert_ne!(weights_1, weights_2); weights_1.copy_from(&weights_2); assert_ne!(weights_1, weights_2); assert_eq!(weights_1.as_slice(), &weights_2[..weights_1.len()]); } } #[test] fn weights_test_10() { const OUT: usize = 7; const IN: usize = 13; let mut rng = ChobitRand::new("weights_test_8".as_bytes()); { let mut weights_1 = Weights::::new(true); rand_weights(&mut rng, &mut weights_1); let mut weights_2 = Weights::::new(true); rand_weights(&mut rng, &mut weights_2); assert_ne!(weights_1, weights_2); weights_1.copy_to(&mut weights_2); assert_eq!(weights_1, weights_2); } { let mut weights_1 = Weights::::new(false); rand_weights(&mut rng, &mut weights_1); let mut weights_2 = Weights::::new(false); rand_weights(&mut rng, &mut weights_2); assert_ne!(weights_1, weights_2); weights_1.copy_to(&mut weights_2); assert_eq!(weights_1, weights_2); } { let mut weights_1 = Weights::::new(true); rand_weights(&mut rng, &mut weights_1); let mut weights_2 = Weights::::new(false); rand_weights(&mut rng, &mut weights_2); assert_ne!(weights_1, weights_2); weights_1.copy_to(&mut weights_2); assert_ne!(weights_1, weights_2); assert_eq!(&weights_1[..weights_2.len()], weights_2.as_slice()); } { let mut weights_1 = Weights::::new(false); rand_weights(&mut rng, &mut weights_1); let mut weights_2 = Weights::::new(true); rand_weights(&mut rng, &mut weights_2); assert_ne!(weights_1, weights_2); weights_1.copy_to(&mut weights_2); assert_ne!(weights_1, weights_2); assert_eq!(weights_1.as_slice(), &weights_2[..weights_1.len()]); } } #[test] fn layer_test_1() { const OUT: usize = 7; const IN: usize = 13; // ready let mut rng = ChobitRand::new("layer_test_1".as_bytes()); let mut layer_1 = Layer::::new(Activation::SoftSign, true); rand_weights(&mut rng, layer_1.mut_weights()); let mut layer_2 = Layer::::new(Activation::SoftSign, true); rand_weights(&mut rng, layer_2.mut_weights()); assert_ne!(layer_1, layer_2); let mut input = MathVec::::new(); rand_math_vec(&mut rng, &mut input); let mut state = MathVec::::new(); rand_math_vec(&mut rng, &mut state); let mut output_1 = MathVec::::new(); let mut output_2 = MathVec::::new(); layer_1.calc(&input, Some(&state), &mut output_1); layer_2.calc(&input, Some(&state), &mut output_2); // checks before machine learning. const EPSILON_1: f32 = 0.01; for i in 0..OUT { let diff = (output_1[i] - output_2[i]).abs(); assert!(diff > EPSILON_1); } // machine learning. const EPOCH: usize = 1000; const BATCH_SIZE: usize = 10; const RATE: f32 = 0.1; let mut ml_layer = MlLayer::new(layer_2); let mut cache = MlCache::new(); let mut output_error = MathVec::::new(); let mut prev_state_error = MathVec::::new(); let mut input_error = MathVec::::new(); let mut state_error = MathVec::::new(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { ml_layer.ready(&input, Some(&state), &mut cache); cache.calc_output_error(&output_1, &mut output_error); prev_state_error.clear(); ml_layer.study( &output_error, Some(&prev_state_error), &cache, &mut input_error, Some(&mut state_error) ); } ml_layer.update(RATE); } let layer_2 = ml_layer.drop(); layer_1.calc(&input, Some(&state), &mut output_1); layer_2.calc(&input, Some(&state), &mut output_2); // checks after machine learning. const EPSILON_2: f32 = 0.000001; for i in 0..OUT { let diff = (output_1[i] - output_2[i]).abs(); assert!(diff < EPSILON_2); } } #[test] fn layer_test_2() { const OUT: usize = 7; const IN: usize = 13; // ready let mut rng = ChobitRand::new("layer_test_2".as_bytes()); let mut layer_1 = Layer::::new(Activation::SoftSign, false); rand_weights(&mut rng, layer_1.mut_weights()); let mut layer_2 = Layer::::new(Activation::SoftSign, false); rand_weights(&mut rng, layer_2.mut_weights()); assert_ne!(layer_1, layer_2); let mut input = MathVec::::new(); rand_math_vec(&mut rng, &mut input); let mut output_1 = MathVec::::new(); let mut output_2 = MathVec::::new(); layer_1.calc(&input, None, &mut output_1); layer_2.calc(&input, None, &mut output_2); // checks before machine learning. const EPSILON_1: f32 = 0.05; for i in 0..OUT { let diff = (output_1[i] - output_2[i]).abs(); assert!(diff > EPSILON_1); } // machine learning. const EPOCH: usize = 1000; const BATCH_SIZE: usize = 10; const RATE: f32 = 0.1; let mut ml_layer = MlLayer::new(layer_2); let mut cache = MlCache::new(); let mut output_error = MathVec::::new(); let mut input_error = MathVec::::new(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { ml_layer.ready(&input, None, &mut cache); cache.calc_output_error(&output_1, &mut output_error); ml_layer.study( &output_error, None, &cache, &mut input_error, None ); } ml_layer.update(RATE); } let layer_2 = ml_layer.drop(); layer_1.calc(&input, None, &mut output_1); layer_2.calc(&input, None, &mut output_2); // checks after machine learning. const EPSILON_2: f32 = 0.000001; for i in 0..OUT { let diff = (output_1[i] - output_2[i]).abs(); assert!(diff < EPSILON_2); } } #[test] fn chobit_ai_test_1() { const OUT: usize = 8; const MIDDLE: usize = 32; const IN: usize = 16; const COUNT: usize = 100; let mut rng = ChobitRand::new("chobit_ai_test_1".as_bytes()); let mut ai = ChobitAi::::new(Activation::SoftSign); let mut input = MathVec::::new(); let mut output = MathVec::::new(); let mut tmpbuf = MathVec::::new(); rand_weights(&mut rng, ai.middle_layer_mut().mut_weights()); rand_weights(&mut rng, ai.output_layer_mut().mut_weights()); for _ in 0..COUNT { let label_in = rng.next_u64() as u16; input.load_u16_label(label_in); ai.calc(&input, &mut output, &mut tmpbuf); } const EPOCH: usize = 10; const BATCH_SIZE: usize = 10; const RATE: f32 = 0.01; let mut ai = ChobitMlAi::::new(ai); let mut cache = MlAiCache::::new(); let mut output_error = MathVec::::new(); let mut input_error = MathVec::::new(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { let label = rng.next_u64() as u32; input.load_u16_label(label as u16); output.load_u8_label(label as u8); ai.ready(&input, &mut cache); cache.calc_output_error(&output, &mut output_error); ai.study(&output_error, &cache, &mut input_error); } ai.update(RATE); } let ai = ai.drop(); for _ in 0..COUNT { let label_in = rng.next_u64() as u16; input.load_u16_label(label_in); ai.calc(&input, &mut output, &mut tmpbuf); } } #[cfg(not(debug_assertions))] #[test] fn chobit_ai_test_2() { const OUT: usize = 32; const MIDDLE: usize = 128; const IN: usize = 32; const COUNT: usize = 100; let mut rng = ChobitRand::new("chobit_ai_test_2".as_bytes()); let mut ai = ChobitAi::::new(Activation::SoftSign); let mut input = MathVec::::new(); let mut output = MathVec::::new(); let mut tmpbuf = MathVec::::new(); rand_weights(&mut rng, ai.middle_layer_mut().mut_weights()); rand_weights(&mut rng, ai.output_layer_mut().mut_weights()); // before machine learning. for _ in 0..COUNT { let label_in = rng.next_u64() as u32; input.load_u32_label(label_in); ai.calc(&input, &mut output, &mut tmpbuf); let label_out = output.to_u32_label(); assert_ne!(label_out, label_in); } // machine learning. const EPOCH: usize = 3000; const BATCH_SIZE: usize = 100; const RATE: f32 = 0.01; let mut ai = ChobitMlAi::::new(ai); let mut cache = MlAiCache::::new(); let mut output_error = MathVec::::new(); let mut input_error = MathVec::::new(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { let label = rng.next_u64() as u32; input.load_u32_label(label); output.load_u32_label(label); ai.ready(&input, &mut cache); cache.calc_output_error(&output, &mut output_error); ai.study(&output_error, &cache, &mut input_error); } ai.update(RATE); } let ai = ai.drop(); // after machine learning. for _ in 0..COUNT { let label_in = rng.next_u64() as u32; input.load_u32_label(label_in); ai.calc(&input, &mut output, &mut tmpbuf); let label_out = output.to_u32_label(); assert_eq!(label_out, label_in); } } #[test] fn chobit_ai_test_3() { const OUT: usize = 11; const MIDDLE: usize = 7; const IN: usize = 5; let mut rng = ChobitRand::new("chobit_ai_test_3".as_bytes()); let mut ai_1 = ChobitAi::::new(Activation::SoftSign); let mut ai_2 = ChobitAi::::new(Activation::SoftSign); ai_1.for_each_weight_mut(|val| { *val = rand_num(&mut rng); }); ai_2.for_each_weight_mut(|val| { *val = rand_num(&mut rng); }); assert_ne!(ai_1, ai_2); let mut vec = Vec::::new(); ai_1.for_each_weight(|val| { vec.push(*val); }); let mut vec_iter = vec.iter(); ai_2.for_each_weight_mut(|val| { *val = *vec_iter.next().unwrap(); }); assert_eq!(ai_1, ai_2); } #[test] fn chobit_ai_test_4() { const OUT: usize = 11; const MIDDLE: usize = 7; const IN: usize = 5; let mut rng = ChobitRand::new("chobit_ai_test_4".as_bytes()); let mut ai_1 = ChobitMlAi::::new( ChobitAi::::new(Activation::SoftSign) ); ai_1.for_each_total_grad_mut(|val| {*val = rand_num(&mut rng)}); let mut ai_2 = ChobitMlAi::::new( ChobitAi::::new(Activation::SoftSign) ); ai_2.for_each_total_grad_mut(|val| {*val = rand_num(&mut rng)}); assert_ne!(ai_1, ai_2); let mut vec = Vec::::new(); ai_1.for_each_total_grad(|val| { vec.push(*val); }); let mut vec_iter = vec.iter(); ai_2.for_each_total_grad_mut(|val| { *val = *vec_iter.next().unwrap(); }); assert_eq!(ai_1, ai_2); } fn letter_data( rng: &mut ChobitRand, letters: &[char], data: &mut Vec> ) { static DUMMY: [char; 10] = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ]; let half_size: usize = ((rng.next_u64() % 5) + 1) as usize; data.resize(half_size * 2, MathVec::<32>::new()); data[..half_size].iter_mut().for_each(|vec| { let letter = letters[(rng.next_u64() as usize) % letters.len()]; let label = letter as u32; vec.load_u32_label(label); }); data[half_size..].iter_mut().for_each(|vec| { let letter = DUMMY[(rng.next_u64() as usize) % DUMMY.len()]; let label = letter as u32; vec.load_u32_label(label); }); rng.shuffle(data); } const JAPANESE: char = '日'; fn japanese_data(rng: &mut ChobitRand, data: &mut Vec>) { let letters: [char; 10] = [ 'あ', 'い', 'う', 'え', 'お', 'か', 'き', 'く', 'け', 'こ' ]; letter_data(rng, &letters, data); } #[cfg(not(debug_assertions))] const ENGLISH: char = 'E'; #[cfg(not(debug_assertions))] fn english_data(rng: &mut ChobitRand, data: &mut Vec>) { let letters: [char; 10] = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' ]; letter_data(rng, &letters, data); } #[cfg(not(debug_assertions))] fn data_to_string(data: &[MathVec<32>]) -> String { let mut ret = String::new(); data.iter().for_each(|vec| { let label = vec.to_u32_label(); ret.push(char::from_u32(label).unwrap()); }); ret } fn gen_lstm( rng: &mut ChobitRand ) -> Lstm { let mut ret = Lstm::::new(); rand_weights(rng, ret.main_layer_mut().mut_weights()); rand_weights(rng, ret.f_gate_mut().mut_weights()); rand_weights(rng, ret.i_gate_mut().mut_weights()); rand_weights(rng, ret.o_gate_mut().mut_weights()); ret } fn gen_layer( rng: &mut ChobitRand ) -> Layer { let mut ret = Layer::::new(Activation::SoftSign, false); rand_weights(rng, ret.mut_weights()); ret } #[test] fn lstm_test_1() { const OUT: usize = 32; const IN: usize = 32; let mut rng = ChobitRand::new("lstm_test_1".as_bytes()); let mut data = Vec::>::new(); let mut japanese = MathVec::::new(); japanese.load_u32_label(JAPANESE as u32); let mut prev_state = MathVec::::new(); let mut output = MathVec::::new(); let mut state = MathVec::::new(); let mut tmpbuf = MathVec::::new(); const COUNT: usize = 10; let lstm = gen_lstm::(&mut rng); let output_layer = gen_layer::(&mut rng); for _ in 0..COUNT { japanese_data(&mut rng, &mut data); prev_state.clear(); for i in 0..(data.len() - 1) { lstm.calc_state( &data[i], &prev_state, &mut state, &mut tmpbuf, ); prev_state.copy_from(&state); } prev_state.copy_from(&state); lstm.calc( data.last().unwrap(), &prev_state, &mut output, &mut state, &mut tmpbuf ); tmpbuf.copy_from(&output); output_layer.calc(&tmpbuf, None, &mut output); } const EPOCH: usize = 10; const BATCH_SIZE: usize = 10; const RATE: f32 = 0.01; let mut lstm = MlLstm::::new(lstm); let mut output_layer = MlLayer::::new(output_layer); let mut lstm_state_caches = vec![MlLstmStateCache::::new(); 30]; let mut lstm_output_cache = MlLstmOutputCache::::new(); let mut output_layer_cache = MlCache::::new(); let mut output_error = MathVec::::new(); let mut state_error = MathVec::::new(); let mut input_error = MathVec::::new(); let mut tmp_input_error = MathVec::::new(); let mut prev_state_error = MathVec::::new(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { japanese_data(&mut rng, &mut data); prev_state.clear(); for i in 0..data.len() { lstm.ready_state_cache( &data[i], &prev_state, &mut lstm_state_caches[i] ); prev_state.copy_from(&lstm_state_caches[i].state()); } let tail: usize = data.len() - 1; lstm.ready_output_cache( &lstm_state_caches[tail], &mut lstm_output_cache ); output_layer.ready( lstm_output_cache.output(), None, &mut output_layer_cache ); output_layer_cache.calc_output_error(&japanese, &mut output_error); tmpbuf.copy_from(&output_error); output_layer.study( &tmpbuf, None, &output_layer_cache, &mut output_error, None ); state_error.clear(); lstm.study( &output_error, &state_error, &lstm_state_caches[tail], &lstm_output_cache, &mut input_error, &mut prev_state_error ); state_error.copy_from(&prev_state_error); for i in 1..data.len() { let i = tail - i; lstm.study_state( &state_error, &lstm_state_caches[i], &mut tmp_input_error, &mut prev_state_error ); input_error += &tmp_input_error; state_error.copy_from(&prev_state_error); } } lstm.update(RATE); output_layer.update(RATE); } } #[cfg(not(debug_assertions))] #[test] fn lstm_test_2() { const OUT: usize = 32; const IN: usize = 32; let mut rng = ChobitRand::new("lstm_test_2".as_bytes()); let mut data = Vec::>::new(); let mut japanese = MathVec::::new(); japanese.load_u32_label(JAPANESE as u32); let mut english = MathVec::::new(); english.load_u32_label(ENGLISH as u32); let mut prev_state = MathVec::::new(); let mut output = MathVec::::new(); let mut state = MathVec::::new(); let mut tmpbuf = MathVec::::new(); const COUNT: usize = 10; let lstm = gen_lstm::(&mut rng); let output_layer = gen_layer::(&mut rng); for _ in 0..COUNT { japanese_data(&mut rng, &mut data); prev_state.clear(); for i in 0..(data.len() - 1) { lstm.calc_state( &data[i], &prev_state, &mut state, &mut tmpbuf, ); prev_state.copy_from(&state); } prev_state.copy_from(&state); lstm.calc( data.last().unwrap(), &prev_state, &mut output, &mut state, &mut tmpbuf ); tmpbuf.copy_from(&output); output_layer.calc(&tmpbuf, None, &mut output); assert_ne!( output.to_u32_label(), japanese.to_u32_label(), ); english_data(&mut rng, &mut data); prev_state.clear(); for i in 0..data.len() { lstm.calc_state( &data[i], &prev_state, &mut state, &mut tmpbuf, ); prev_state.copy_from(&state); } prev_state.copy_from(&state); lstm.calc( data.last().unwrap(), &prev_state, &mut output, &mut state, &mut tmpbuf ); tmpbuf.copy_from(&output); output_layer.calc(&tmpbuf, None, &mut output); assert_ne!( output.to_u32_label(), english.to_u32_label(), ); } const EPOCH: usize = 1000; const BATCH_SIZE: usize = 100; const RATE: f32 = 0.01; let mut lstm = MlLstm::::new(lstm); let mut output_layer = MlLayer::::new(output_layer); let mut lstm_state_caches = vec![MlLstmStateCache::::new(); 30]; let mut lstm_output_cache = MlLstmOutputCache::::new(); let mut output_layer_cache = MlCache::::new(); let mut output_error = MathVec::::new(); let mut state_error = MathVec::::new(); let mut input_error = MathVec::::new(); let mut tmp_input_error = MathVec::::new(); let mut prev_state_error = MathVec::::new(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { japanese_data(&mut rng, &mut data); prev_state.clear(); for i in 0..data.len() { lstm.ready_state_cache( &data[i], &prev_state, &mut lstm_state_caches[i] ); prev_state.copy_from(&lstm_state_caches[i].state()); } let tail: usize = data.len() - 1; lstm.ready_output_cache( &lstm_state_caches[tail], &mut lstm_output_cache ); output_layer.ready( lstm_output_cache.output(), None, &mut output_layer_cache ); output_layer_cache.calc_output_error(&japanese, &mut output_error); tmpbuf.copy_from(&output_error); output_layer.study( &tmpbuf, None, &output_layer_cache, &mut output_error, None ); state_error.clear(); lstm.study( &output_error, &state_error, &lstm_state_caches[tail], &lstm_output_cache, &mut input_error, &mut prev_state_error ); state_error.copy_from(&prev_state_error); for i in 1..data.len() { let i = tail - i; lstm.study_state( &state_error, &lstm_state_caches[i], &mut tmp_input_error, &mut prev_state_error ); input_error += &tmp_input_error; state_error.copy_from(&prev_state_error); } english_data(&mut rng, &mut data); prev_state.clear(); for i in 0..data.len() { lstm.ready_state_cache( &data[i], &prev_state, &mut lstm_state_caches[i] ); prev_state.copy_from(&lstm_state_caches[i].state()); } let tail: usize = data.len() - 1; lstm.ready_output_cache( &lstm_state_caches[tail], &mut lstm_output_cache ); output_layer.ready( lstm_output_cache.output(), None, &mut output_layer_cache ); output_layer_cache.calc_output_error(&english, &mut output_error); tmpbuf.copy_from(&output_error); output_layer.study( &tmpbuf, None, &output_layer_cache, &mut output_error, None ); state_error.clear(); lstm.study( &output_error, &state_error, &lstm_state_caches[tail], &lstm_output_cache, &mut input_error, &mut prev_state_error ); state_error.copy_from(&prev_state_error); for i in 1..data.len() { let i = tail - i; lstm.study_state( &state_error, &lstm_state_caches[i], &mut tmp_input_error, &mut prev_state_error ); input_error += &tmp_input_error; state_error.copy_from(&prev_state_error); } } lstm.update(RATE); output_layer.update(RATE); } let lstm = lstm.drop(); let output_layer = output_layer.drop(); for _ in 0..COUNT { japanese_data(&mut rng, &mut data); prev_state.clear(); for i in 0..(data.len() - 1) { lstm.calc_state( &data[i], &prev_state, &mut state, &mut tmpbuf, ); prev_state.copy_from(&state); } prev_state.copy_from(&state); lstm.calc( data.last().unwrap(), &prev_state, &mut output, &mut state, &mut tmpbuf ); tmpbuf.copy_from(&output); output_layer.calc(&tmpbuf, None, &mut output); assert_eq!( output.to_u32_label(), japanese.to_u32_label(), ); english_data(&mut rng, &mut data); prev_state.clear(); for i in 0..(data.len() - 1) { lstm.calc_state( &data[i], &prev_state, &mut state, &mut tmpbuf, ); prev_state.copy_from(&state); } prev_state.copy_from(&state); lstm.calc( data.last().unwrap(), &prev_state, &mut output, &mut state, &mut tmpbuf ); tmpbuf.copy_from(&output); output_layer.calc(&tmpbuf, None, &mut output); assert_eq!( output.to_u32_label(), english.to_u32_label(), ); } } #[test] fn lstm_test_3() { const OUT: usize = 11; const IN: usize = 5; let mut rng = ChobitRand::new("lstm_test_3".as_bytes()); let mut lstm_1 = Lstm::::new(); let mut lstm_2 = Lstm::::new(); lstm_1.for_each_weight_mut(|val| { *val = rand_num(&mut rng); }); lstm_2.for_each_weight_mut(|val| { *val = rand_num(&mut rng); }); assert_ne!(lstm_1, lstm_2); let mut vec = Vec::::new(); lstm_1.for_each_weight(|val| { vec.push(*val); }); let mut vec_iter = vec.iter(); lstm_2.for_each_weight_mut(|val| { *val = *vec_iter.next().unwrap(); }); assert_eq!(lstm_1, lstm_2); } #[test] fn lstm_test_4() { const OUT: usize = 11; const IN: usize = 5; let mut rng = ChobitRand::new("lstm_test_4".as_bytes()); let mut lstm_1 = MlLstm::::new( Lstm::::new() ); lstm_1.for_each_total_grad_mut(|val| {*val = rand_num(&mut rng)}); let mut lstm_2 = MlLstm::::new( Lstm::::new() ); lstm_2.for_each_total_grad_mut(|val| {*val = rand_num(&mut rng)}); assert_ne!(lstm_1, lstm_2); let mut vec = Vec::::new(); lstm_1.for_each_total_grad(|val| { vec.push(*val); }); let mut vec_iter = vec.iter(); lstm_2.for_each_total_grad_mut(|val| { *val = *vec_iter.next().unwrap(); }); assert_eq!(lstm_1, lstm_2); } fn gen_encoder< const OUT: usize, const MIDDLE: usize, const IN: usize >(rng: &mut ChobitRand) -> ChobitEncoder { let mut ret = ChobitEncoder::::new(Activation::SoftSign); rand_weights(rng, ret.lstm_mut().main_layer_mut().mut_weights()); rand_weights(rng, ret.lstm_mut().f_gate_mut().mut_weights()); rand_weights(rng, ret.lstm_mut().i_gate_mut().mut_weights()); rand_weights(rng, ret.lstm_mut().o_gate_mut().mut_weights()); rand_weights(rng, ret.output_layer_mut().mut_weights()); ret } #[test] fn chobit_encoder_test_1() { const OUT: usize = 32; const MIDDLE: usize = 64; const IN: usize = 32; let mut rng = ChobitRand::new("chobit_encoder_test_1".as_bytes()); let mut data = Vec::>::new(); let mut japanese = MathVec::::new(); japanese.load_u32_label(JAPANESE as u32); const COUNT: usize = 10; let mut encoder = gen_encoder::(&mut rng); let mut output = MathVec::::new(); for _ in 0..COUNT { japanese_data(&mut rng, &mut data); encoder.state_mut().clear(); data.iter().for_each(|data_one| { encoder.input_next(data_one); }); encoder.output(&mut output); } const EPOCH: usize = 10; const BATCH_SIZE: usize = 10; const RATE: f32 = 0.01; let mut encoder = ChobitMlEncoder::::new(encoder); let prev_state = MathVec::::new(); let mut cache = MlEncoderCache::::new(0); let mut output_error = MathVec::::new(); let mut input_error = vec![MathVec::::new(); 30]; let mut prev_state_error = MathVec::::new(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { japanese_data(&mut rng, &mut data); encoder.ready(&data, &prev_state, &mut cache); cache.calc_output_error(&japanese, &mut output_error); encoder.study( &output_error, &cache, &mut input_error[..data.len()], &mut prev_state_error ); } encoder.update(RATE); } } #[cfg(not(debug_assertions))] #[test] fn chobit_encoder_test_2() { const OUT: usize = 32; const MIDDLE: usize = 64; const IN: usize = 32; let mut rng = ChobitRand::new("chobit_encoder_test_2".as_bytes()); let mut data = Vec::>::new(); let mut japanese = MathVec::::new(); japanese.load_u32_label(JAPANESE as u32); let mut english = MathVec::::new(); english.load_u32_label(ENGLISH as u32); const COUNT: usize = 10; let mut encoder = gen_encoder::(&mut rng); let mut output = MathVec::::new(); for _ in 0..COUNT { japanese_data(&mut rng, &mut data); encoder.state_mut().clear(); data.iter().for_each(|data_one| { encoder.input_next(data_one); }); encoder.output(&mut output); assert_ne!( output.to_u32_label(), japanese.to_u32_label(), ); println!( "{}, {:?}", data_to_string(&data), char::from_u32(output.to_u32_label()) ) } for _ in 0..COUNT { english_data(&mut rng, &mut data); encoder.state_mut().clear(); data.iter().for_each(|data_one| { encoder.input_next(data_one); }); encoder.output(&mut output); assert_ne!( output.to_u32_label(), english.to_u32_label(), ); println!( "{}, {:?}", data_to_string(&data), char::from_u32(output.to_u32_label()) ) } const EPOCH: usize = 1000; const BATCH_SIZE: usize = 100; const RATE: f32 = 0.01; let mut encoder = ChobitMlEncoder::::new(encoder); let prev_state = MathVec::::new(); let mut cache = MlEncoderCache::::new(0); let mut output_error = MathVec::::new(); let mut input_error = vec![MathVec::::new(); 30]; let mut prev_state_error = MathVec::::new(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { japanese_data(&mut rng, &mut data); encoder.ready(&data, &prev_state, &mut cache); cache.calc_output_error(&japanese, &mut output_error); encoder.study( &output_error, &cache, &mut input_error[..data.len()], &mut prev_state_error ); english_data(&mut rng, &mut data); encoder.ready(&data, &prev_state, &mut cache); cache.calc_output_error(&english, &mut output_error); encoder.study( &output_error, &cache, &mut input_error[..data.len()], &mut prev_state_error ); } encoder.update(RATE); } let mut encoder = encoder.drop(); for _ in 0..COUNT { japanese_data(&mut rng, &mut data); encoder.state_mut().clear(); data.iter().for_each(|data_one| { encoder.input_next(data_one); }); encoder.output(&mut output); assert_eq!( output.to_u32_label(), japanese.to_u32_label(), ); println!( "{}, {:?}", data_to_string(&data), char::from_u32(output.to_u32_label()) ) } for _ in 0..COUNT { english_data(&mut rng, &mut data); encoder.state_mut().clear(); data.iter().for_each(|data_one| { encoder.input_next(data_one); }); encoder.output(&mut output); assert_eq!( output.to_u32_label(), english.to_u32_label(), ); println!( "{}, {:?}", data_to_string(&data), char::from_u32(output.to_u32_label()) ) } } #[test] fn chobit_encoder_test_3() { const OUT: usize = 11; const MIDDLE: usize = 7; const IN: usize = 5; let mut rng = ChobitRand::new("chobit_encoder_test_3".as_bytes()); let mut encoder_1 = ChobitEncoder::::new(Activation::SoftSign); encoder_1.for_each_weight_mut(|val| { *val = rand_num(&mut rng); }); let mut encoder_2 = ChobitEncoder::::new(Activation::SoftSign); encoder_2.for_each_weight_mut(|val| { *val = rand_num(&mut rng); }); assert_ne!(encoder_1, encoder_2); let mut vec = Vec::::new(); encoder_1.for_each_weight(|val| { vec.push(*val); }); let mut vec_iter = vec.iter(); encoder_2.for_each_weight_mut(|val| { *val = *vec_iter.next().unwrap(); }); assert_eq!(encoder_1, encoder_2); } #[test] fn chobit_encoder_test_4() { const OUT: usize = 11; const MIDDLE: usize = 7; const IN: usize = 5; let mut rng = ChobitRand::new("chobit_encoder_test_4".as_bytes()); let mut encoder_1 = ChobitMlEncoder::::new( ChobitEncoder::::new(Activation::SoftSign) ); encoder_1.for_each_total_grad_mut(|val| {*val = rand_num(&mut rng)}); let mut encoder_2 = ChobitMlEncoder::::new( ChobitEncoder::::new(Activation::SoftSign) ); encoder_2.for_each_total_grad_mut(|val| {*val = rand_num(&mut rng)}); assert_ne!(encoder_1, encoder_2); let mut vec = Vec::::new(); encoder_1.for_each_total_grad(|val| { vec.push(*val); }); let mut vec_iter = vec.iter(); encoder_2.for_each_total_grad_mut(|val| { *val = *vec_iter.next().unwrap(); }); assert_eq!(encoder_1, encoder_2); } fn gen_decoder< const OUT: usize, const MIDDLE: usize, const IN: usize >(rng: &mut ChobitRand) -> ChobitDecoder { let mut ret = ChobitDecoder::::new(Activation::SoftSign); rand_weights(rng, ret.lstm_mut().main_layer_mut().mut_weights()); rand_weights(rng, ret.lstm_mut().f_gate_mut().mut_weights()); rand_weights(rng, ret.lstm_mut().i_gate_mut().mut_weights()); rand_weights(rng, ret.lstm_mut().o_gate_mut().mut_weights()); rand_weights(rng, ret.output_layer_mut().mut_weights()); ret } #[test] fn chobit_decoder_test_1() { const OUT: usize = 32; const MIDDLE: usize = 64; const IN: usize = 32; let mut rng = ChobitRand::new("chobit_decoder_test_1".as_bytes()); let mut japanese_in = MathVec::::new(); japanese_in.load_u32_label(JAPANESE as u32); let mut japanese_out = Vec::>::new(); "これは日本語です。\x00".chars().for_each(|c| { let mut vec = MathVec::::new(); vec.load_u32_label(c as u32); japanese_out.push(vec); }); let mut decoder = gen_decoder(&mut rng); { decoder.input_mut().copy_from(&japanese_in); decoder.state_mut().clear(); let mut output = vec![MathVec::::new(); japanese_out.len()]; output.iter_mut().for_each(|output_one| { decoder.output_next(output_one); }); } const EPOCH: usize = 3; const BATCH_SIZE: usize = 3; const RATE: f32 = 0.01; let mut decoder = ChobitMlDecoder::::new(decoder); let mut cache = MlDecoderCache::::new(japanese_out.len()); let prev_state = MathVec::::new(); let mut output_error = vec![MathVec::::new(); 30]; let mut input_error = MathVec::::new(); let mut prev_state_error = MathVec::::new(); let japanese_out_len = japanese_out.len(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { decoder.ready( &japanese_in, &prev_state, japanese_out_len, &mut cache ); cache.calc_output_error( japanese_out.as_slice(), &mut output_error[..japanese_out_len] ); decoder.study( &output_error[..japanese_out_len], &cache, &mut input_error, &mut prev_state_error ); } decoder.update(RATE); } } #[cfg(not(debug_assertions))] #[test] fn chobit_decoder_test_2() { const OUT: usize = 32; const MIDDLE: usize = 64; const IN: usize = 32; let mut rng = ChobitRand::new("chobit_decoder_test_1".as_bytes()); let mut japanese_in = MathVec::::new(); japanese_in.load_u32_label(JAPANESE as u32); let mut japanese_out = Vec::>::new(); "これは日本語です。\x00".chars().for_each(|c| { let mut vec = MathVec::::new(); vec.load_u32_label(c as u32); japanese_out.push(vec); }); let mut english_in = MathVec::::new(); english_in.load_u32_label(ENGLISH as u32); let mut english_out = Vec::>::new(); "this is english.\x00".chars().for_each(|c| { let mut vec = MathVec::::new(); vec.load_u32_label(c as u32); english_out.push(vec); }); let mut decoder = gen_decoder(&mut rng); { decoder.input_mut().copy_from(&japanese_in); decoder.state_mut().clear(); let mut output = vec![MathVec::::new(); japanese_out.len()]; output.iter_mut().for_each(|output_one| { decoder.output_next(output_one); }); assert_ne!(output, japanese_out); } { decoder.input_mut().copy_from(&english_in); decoder.state_mut().clear(); let mut output = vec![MathVec::::new(); english_out.len()]; output.iter_mut().for_each(|output_one| { decoder.output_next(output_one); }); assert_ne!(output, english_out); } const EPOCH: usize = 50000; const BATCH_SIZE: usize = 1; const RATE: f32 = 0.01; let mut decoder = ChobitMlDecoder::::new(decoder); let mut cache = MlDecoderCache::::new(japanese_out.len()); let prev_state_j = MathVec::::new(); let prev_state_e = MathVec::::new(); let mut output_error = vec![MathVec::::new(); 30]; let mut input_error = MathVec::::new(); let mut prev_state_error = MathVec::::new(); let japanese_out_len = japanese_out.len(); let english_out_len = english_out.len(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { decoder.ready( &japanese_in, &prev_state_j, japanese_out_len, &mut cache ); cache.calc_output_error( japanese_out.as_slice(), &mut output_error[..japanese_out_len] ); decoder.study( &output_error[..japanese_out_len], &cache, &mut input_error, &mut prev_state_error ); decoder.ready( &english_in, &prev_state_e, english_out_len, &mut cache ); cache.calc_output_error( english_out.as_slice(), &mut output_error[..english_out_len] ); decoder.study( &output_error[..english_out_len], &cache, &mut input_error, &mut prev_state_error ); } decoder.update(RATE); } let mut decoder = decoder.drop(); { decoder.input_mut().copy_from(&japanese_in); decoder.state_mut().clear(); let mut output = vec![MathVec::::new(); japanese_out.len()]; output.iter_mut().for_each(|output_one| { decoder.output_next(output_one); println!("{:?}", char::from_u32(output_one.to_u32_label())); }); assert_eq!( data_to_string(output.as_slice()), data_to_string(japanese_out.as_slice()) ); } println!("-----"); { decoder.input_mut().copy_from(&english_in); decoder.state_mut().clear(); let mut output = vec![MathVec::::new(); english_out.len()]; output.iter_mut().for_each(|output_one| { decoder.output_next(output_one); println!("{:?}", char::from_u32(output_one.to_u32_label())); }); assert_eq!( data_to_string(output.as_slice()), data_to_string(english_out.as_slice()) ); } } #[test] fn chobit_decoder_test_3() { const OUT: usize = 11; const MIDDLE: usize = 7; const IN: usize = 5; let mut rng = ChobitRand::new("chobit_decoder_test_3".as_bytes()); let mut decoder_1 = ChobitDecoder::::new(Activation::SoftSign); decoder_1.for_each_weight_mut(|val| { *val = rand_num(&mut rng); }); let mut decoder_2 = ChobitDecoder::::new(Activation::SoftSign); decoder_2.for_each_weight_mut(|val| { *val = rand_num(&mut rng); }); assert_ne!(decoder_1, decoder_2); let mut vec = Vec::::new(); decoder_1.for_each_weight(|val| { vec.push(*val); }); let mut vec_iter = vec.iter(); decoder_2.for_each_weight_mut(|val| { *val = *vec_iter.next().unwrap(); }); assert_eq!(decoder_1, decoder_2); } #[test] fn chobit_decoder_test_4() { const OUT: usize = 11; const MIDDLE: usize = 7; const IN: usize = 5; let mut rng = ChobitRand::new("chobit_decoder_test_4".as_bytes()); let mut decoder_1 = ChobitMlDecoder::::new( ChobitDecoder::::new(Activation::SoftSign) ); decoder_1.for_each_total_grad_mut(|val| {*val = rand_num(&mut rng)}); let mut decoder_2 = ChobitMlDecoder::::new( ChobitDecoder::::new(Activation::SoftSign) ); decoder_2.for_each_total_grad_mut(|val| {*val = rand_num(&mut rng)}); assert_ne!(decoder_1, decoder_2); let mut vec = Vec::::new(); decoder_1.for_each_total_grad(|val| { vec.push(*val); }); let mut vec_iter = vec.iter(); decoder_2.for_each_total_grad_mut(|val| { *val = *vec_iter.next().unwrap(); }); assert_eq!(decoder_1, decoder_2); } fn gen_seq_ai< const OUT: usize, const MIDDLE: usize, const IN: usize >(rng: &mut ChobitRand) -> ChobitSeqAi { let mut ret = ChobitSeqAi::::new(Activation::SoftSign); rand_weights(rng, ret.enc_layer_mut().main_layer_mut().mut_weights()); rand_weights(rng, ret.enc_layer_mut().f_gate_mut().mut_weights()); rand_weights(rng, ret.enc_layer_mut().i_gate_mut().mut_weights()); rand_weights(rng, ret.enc_layer_mut().o_gate_mut().mut_weights()); rand_weights(rng, ret.dec_layer_mut().main_layer_mut().mut_weights()); rand_weights(rng, ret.dec_layer_mut().f_gate_mut().mut_weights()); rand_weights(rng, ret.dec_layer_mut().i_gate_mut().mut_weights()); rand_weights(rng, ret.dec_layer_mut().o_gate_mut().mut_weights()); rand_weights(rng, ret.output_layer_mut().mut_weights()); ret } #[test] fn chobit_seq_ai_test_1() { const OUT: usize = 32; const MIDDLE: usize = 64; const IN: usize = 32; let mut rng = ChobitRand::new("chobit_seq_ai_test_1".as_bytes()); let mut data = Vec::>::new(); let mut japanese_out = Vec::>::new(); "これは日本語です。\x00".chars().for_each(|c| { let mut vec = MathVec::::new(); vec.load_u32_label(c as u32); japanese_out.push(vec); }); let mut ai = gen_seq_ai::(&mut rng); let mut output = vec![MathVec::::new(); 30]; const COUNT: usize = 10; for _ in 0..COUNT { japanese_data(&mut rng, &mut data); ai.state_mut().clear(); data.iter().for_each(|data_one| { ai.input_next(data_one); }); japanese_out.iter().zip(output.as_mut_slice()).for_each( |(_, output_one)| { ai.output_next(output_one); } ); } const EPOCH: usize = 3; const BATCH_SIZE: usize = 3; const RATE: f32 = 0.01; let mut ai = ChobitMlSeqAi::::new(ai); let mut cache = MlSeqAiCache::::new(0, 0); let mut input_error = vec![MathVec::::new(); 30]; let mut output_error = vec![MathVec::::new(); 30]; let mut prev_state_error = MathVec::::new(); let prev_state = MathVec::::new(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { japanese_data(&mut rng, &mut data); ai.ready( &data, &prev_state, japanese_out.len(), &mut cache ); cache.calc_output_error( &japanese_out, &mut output_error[..japanese_out.len()] ); ai.study( &output_error[..japanese_out.len()], &cache, &mut input_error[..data.len()], &mut prev_state_error ); } ai.update(RATE); } } #[cfg(not(debug_assertions))] #[test] fn chobit_seq_ai_test_2() { const OUT: usize = 32; const MIDDLE: usize = 64; const IN: usize = 32; let mut rng = ChobitRand::new("chobit_seq_ai_test_2".as_bytes()); let mut data = Vec::>::new(); let mut japanese_out = Vec::>::new(); "これは日本語です。\x00".chars().for_each(|c| { let mut vec = MathVec::::new(); vec.load_u32_label(c as u32); japanese_out.push(vec); }); let mut english_out = Vec::>::new(); "this is english.\x00".chars().for_each(|c| { let mut vec = MathVec::::new(); vec.load_u32_label(c as u32); english_out.push(vec); }); let mut ai = gen_seq_ai::(&mut rng); let mut output = vec![MathVec::::new(); 30]; const COUNT: usize = 10; for _ in 0..COUNT { japanese_data(&mut rng, &mut data); ai.state_mut().clear(); data.iter().for_each(|data_one| { ai.input_next(data_one); }); japanese_out.iter().zip(output.as_mut_slice()).for_each( |(_, output_one)| { ai.output_next(output_one); } ); japanese_out.iter().zip(output.as_slice()).for_each( |(train_out, output_one)| { assert_ne!( char::from_u32(train_out.to_u32_label()), char::from_u32(output_one.to_u32_label()), ); } ); } for _ in 0..COUNT { english_data(&mut rng, &mut data); ai.state_mut().clear(); data.iter().for_each(|data_one| { ai.input_next(data_one); }); english_out.iter().zip(output.as_mut_slice()).for_each( |(_, output_one)| { ai.output_next(output_one); } ); english_out.iter().zip(output.as_slice()).for_each( |(train_out, output_one)| { assert_ne!( char::from_u32(train_out.to_u32_label()), char::from_u32(output_one.to_u32_label()), ); } ); } const EPOCH: usize = 3000; const BATCH_SIZE: usize = 20; const RATE: f32 = 0.01; let mut ai = ChobitMlSeqAi::::new(ai); let mut cache = MlSeqAiCache::::new(0, 0); let mut input_error = vec![MathVec::::new(); 30]; let mut output_error = vec![MathVec::::new(); 30]; let mut prev_state_error = MathVec::::new(); let prev_state = MathVec::::new(); for _ in 0..EPOCH { for _ in 0..BATCH_SIZE { japanese_data(&mut rng, &mut data); ai.ready( &data, &prev_state, japanese_out.len(), &mut cache ); cache.calc_output_error( &japanese_out, &mut output_error[..japanese_out.len()] ); ai.study( &output_error[..japanese_out.len()], &cache, &mut input_error[..data.len()], &mut prev_state_error ); english_data(&mut rng, &mut data); ai.ready( &data, &prev_state, english_out.len(), &mut cache ); cache.calc_output_error( &english_out, &mut output_error[..english_out.len()] ); ai.study( &output_error[..english_out.len()], &cache, &mut input_error[..data.len()], &mut prev_state_error ); } ai.update(RATE); } let mut ai = ai.drop(); for _ in 0..COUNT { japanese_data(&mut rng, &mut data); ai.state_mut().clear(); data.iter().for_each(|data_one| { ai.input_next(data_one); }); japanese_out.iter().zip(output.as_mut_slice()).for_each( |(_, output_one)| { ai.output_next(output_one); } ); japanese_out.iter().zip(output.as_slice()).for_each( |(train_out, output_one)| { assert_eq!( char::from_u32(train_out.to_u32_label()), char::from_u32(output_one.to_u32_label()), ); } ); println!("{}", data_to_string(&output[..japanese_out.len()])) } for _ in 0..COUNT { english_data(&mut rng, &mut data); ai.state_mut().clear(); data.iter().for_each(|data_one| { ai.input_next(data_one); }); english_out.iter().zip(output.as_mut_slice()).for_each( |(_, output_one)| { ai.output_next(output_one); } ); english_out.iter().zip(output.as_slice()).for_each( |(train_out, output_one)| { assert_eq!( char::from_u32(train_out.to_u32_label()), char::from_u32(output_one.to_u32_label()), ); } ); println!("{}", data_to_string(&output[..english_out.len()])) } } #[test] fn chobit_seq_ai_test_3() { const OUT: usize = 11; const MIDDLE: usize = 7; const IN: usize = 5; let mut rng = ChobitRand::new("chobit_seq_ai_test_3".as_bytes()); let mut ai_1 = ChobitSeqAi::::new(Activation::SoftSign); ai_1.for_each_weight_mut(|val| { *val = rand_num(&mut rng); }); let mut ai_2 = ChobitSeqAi::::new(Activation::SoftSign); ai_2.for_each_weight_mut(|val| { *val = rand_num(&mut rng); }); assert_ne!(ai_1, ai_2); let mut vec = Vec::::new(); ai_1.for_each_weight(|val| { vec.push(*val); }); let mut vec_iter = vec.iter(); ai_2.for_each_weight_mut(|val| { *val = *vec_iter.next().unwrap(); }); assert_eq!(ai_1, ai_2); } #[test] fn chobit_seq_ai_test_4() { const OUT: usize = 11; const MIDDLE: usize = 7; const IN: usize = 5; let mut rng = ChobitRand::new("chobit_seq_ai_test_4".as_bytes()); let mut ai_1 = ChobitMlSeqAi::::new( ChobitSeqAi::::new(Activation::SoftSign) ); ai_1.for_each_total_grad_mut(|val| {*val = rand_num(&mut rng)}); let mut ai_2 = ChobitMlSeqAi::::new( ChobitSeqAi::::new(Activation::SoftSign) ); ai_2.for_each_total_grad_mut(|val| {*val = rand_num(&mut rng)}); assert_ne!(ai_1, ai_2); let mut vec = Vec::::new(); ai_1.for_each_total_grad(|val| { vec.push(*val); }); let mut vec_iter = vec.iter(); ai_2.for_each_total_grad_mut(|val| { *val = *vec_iter.next().unwrap(); }); assert_eq!(ai_1, ai_2); }