#[derive(Debug, Clone)]
pub struct LoraLayer {
pub in_features: usize,
pub out_features: usize,
pub rank: usize,
pub alpha: f32,
pub dropout: f32,
pub active: bool,
}
impl LoraLayer {
pub fn new(in_features: usize, out_features: usize, rank: usize, alpha: f32) -> Self {
Self {
in_features,
out_features,
rank,
alpha,
dropout: 0.0,
active: true,
}
}
pub fn with_dropout(mut self, dropout: f32) -> Self {
self.dropout = dropout;
self
}
pub fn scaling(&self) -> f32 {
self.alpha / self.rank as f32
}
pub fn trainable_params(&self) -> usize {
self.rank * self.in_features + self.out_features * self.rank
}
pub fn frozen_params(&self) -> usize {
self.in_features * self.out_features
}
pub fn compression_ratio(&self) -> f64 {
self.trainable_params() as f64 / (self.frozen_params() + self.trainable_params()) as f64
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lora_layer() {
let layer = LoraLayer::new(4096, 4096, 16, 32.0);
assert_eq!(layer.scaling(), 2.0);
assert_eq!(layer.trainable_params(), 16 * 4096 + 4096 * 16);
assert!(layer.compression_ratio() < 0.01); }
}