L1 정규화(L1 Normalization)란? AI가 벡터 절댓값의 합을 1로 맞추는 방법
TL;DR
L1 정규화(L1 Normalization)는 벡터 성분의 절댓값을 모두 더한 뒤 각 성분을 그 합으로 나누는 연산입니다. 0이 아닌 벡터는 정규화 뒤 절댓값의 합이 1이 되며 부호와 0인 위치는 유지됩니다. 희소한 텍스트 특징과 표본별 비율을 맞출 때 쓸 수 있지만, L2 정규화나 L1 규제와는 계산 목적이 다르고 축과 영벡터 처리에 따라 결과가 달라집니다.
핵심 3줄 요약
- 핵심 1
절댓값의 합으로 나눕니다. 0이 아닌 결과 벡터는 성분 절댓값의 합이 1입니다. - 핵심 2
상대적 비중을 보기 쉽습니다. 특히 값이 0 이상이면 각 성분의 합도 1이 되어 구성 비율을 읽기 편합니다. - 핵심 3
축과 0벡터를 확인해야 합니다. 잘못된 축은 여러 표본을 한 덩어리로 만들고 0으로 나누면 수치 오류가 생깁니다.
이 글에서 다룰 내용
- L1 정규화의 한 문장 정의와 L1 노름의 뜻
- 3과 -1로 이해하는 계산 예시
- 희소한 AI 특징과 상대적 비중에서 중요한 이유
- 절댓값·합계·나눗셈으로 이어지는 작동 순서
- axis·dim·ord·p와 영벡터 처리의 의미
- L2 정규화·합계 정규화·L1 규제·맨해튼 거리와의 차이
- 전처리와 모델 변환에서 확인할 실전 순서
L1 정규화를 한 문장으로 정의하면 무엇인가요?
L1 정규화는 한 벡터의 각 성분을 그 벡터 성분 절댓값의 합인 L1 노름으로 나눠, 결과의 절댓값 합을 1로 만드는 연산입니다. L1 노름은 1-노름이라고도 부릅니다.
벡터에 음수가 있어도 먼저 절댓값을 취해 크기를 더합니다. 모든 성분을 같은 양수로 나누므로 양수와 음수의 부호, 0인 성분의 위치, 벡터가 가리키는 방향은 유지됩니다. 대신 원래 벡터의 전체 크기는 사라집니다.
PyTorch의 normalize 함수는 p 값을 1로 지정하면 L1 노름으로 나누고, scikit-learn의 normalize 함수는 norm을 l1로 선택합니다. TensorFlow의 tf.linalg.normalize는 ord=1을 받을 수 있으며 ONNX LpNormalization은 p 값 1과 2를 구분합니다.
한 줄 정리: L1 정규화는 각 값의 절댓값 합이 1이 되도록 벡터 전체의 크기를 맞춥니다.
쉬운 예시로 이해해 볼까요?
두 성분으로 이루어진 벡터 [3, -1]을 생각해 보겠습니다. 3의 절댓값은 3이고 -1의 절댓값은 1입니다. 둘을 더하면 이 벡터의 L1 노름은 4입니다.
- 첫째, 각 성분의 절댓값을 구해 [3, 1]로 봅니다.
- 둘째, 절댓값을 더해 L1 노름 4를 구합니다.
- 셋째, 원래 성분을 4로 나누면 [0.75, -0.25]가 됩니다.
- 마지막으로 결과의 절댓값 0.75와 0.25를 더하면 1입니다.
음수 성분은 정규화 뒤에도 음수입니다. 벡터 [30, -10]도 L1 정규화하면 [0.75, -0.25]가 됩니다. 두 벡터의 전체 크기는 다르지만 성분 사이의 상대적 관계와 방향은 같습니다.
쉬운 예시: 지출 항목의 금액 크기를 모두 더한 뒤 각 항목이 전체에서 차지하는 몫을 계산하되, 환불처럼 음수인 항목의 부호는 그대로 남기는 과정과 비슷합니다.
왜 AI에서 L1 정규화가 중요한가요?
표본마다 다른 전체 크기를 맞춥니다
문서마다 단어 수가 다르거나 사용자마다 행동 횟수가 다르면 원시 특징 벡터의 전체 크기도 달라집니다. 전체량보다 어떤 특징이 상대적으로 많이 나타났는지가 중요할 때 L1 정규화로 각 표본의 크기를 같은 기준에 놓을 수 있습니다.
희소 벡터의 0인 위치를 유지합니다
단어 빈도나 범주형 특징은 대부분의 성분이 0인 희소 벡터가 되기 쉽습니다. L1 정규화는 각 성분을 하나의 스칼라로 나누므로 원래 0이던 값은 계속 0입니다. 정규화 자체가 새로운 0이 아닌 성분을 만들지는 않습니다.
0 이상인 값은 구성 비율로 읽기 쉬워집니다
모든 성분이 0 이상이면 절댓값을 취해도 값이 바뀌지 않습니다. 이때 정규화한 성분의 합은 1이므로 각 특징의 상대적 몫을 읽기 쉽습니다. 하지만 합이 1이라는 이유만으로 모델의 확률 출력이라고 부를 수는 없습니다. 확률의 의미와 생성 과정은 별도로 확인해야 합니다.
핵심 인사이트: L1 정규화의 장점은 큰 표본과 작은 표본을 절댓값 합 1이라는 같은 기준으로 비교하는 데 있습니다. 원래 총량이 중요한 문제라면 이 변환이 정보를 지울 수 있습니다.
L1 정규화는 어떻게 작동하나요?
1. 하나의 벡터로 볼 축을 정합니다
입력이 [표본 수, 특징 수] 형태라면 보통 각 표본의 특징 축을 따라 노름을 구합니다. 텐서에는 배치·토큰·채널·공간 축이 함께 있을 수 있으므로 어느 축의 절댓값을 더할지 명시해야 합니다. 축을 잘못 고르면 서로 다른 표본의 값을 함께 나누게 됩니다.
2. 각 성분의 절댓값을 구합니다
양수는 그대로 두고 음수는 크기만 봅니다. [3, -1]에서는 [3, 1]을 얻습니다. 원래 값의 부호를 없애는 변환이 아니라 분모를 계산할 때만 절댓값을 사용한다는 점이 중요합니다.
3. 절댓값을 모두 더해 L1 노름을 만듭니다
선택한 축에서 절댓값을 더한 값이 L1 노름입니다. 모든 성분이 0이면 노름도 0입니다. 이때 그대로 나누면 NaN이나 무한대가 생길 수 있어 구현마다 작은 안전값을 쓰거나 결과를 0으로 정의합니다.
4. 원래 성분을 L1 노름으로 나눕니다
원래 값 각각을 같은 분모로 나누면 0이 아닌 벡터의 절댓값 합이 1이 됩니다. PyTorch는 계산한 노름과 eps 중 큰 값을 분모로 사용합니다. ONNX는 선택한 축의 노름이 0이면 출력을 0으로 정의합니다.
한 줄 정리: 축 선택 → 절댓값 → 합계 → 영벡터 보호 → 원래 성분 나누기 순서입니다.
주요 설정과 예외는 무엇인가요?
axis 또는 dim
axis와 dim은 어느 차원을 하나의 벡터로 묶을지 정합니다. scikit-learn은 기본 axis=1로 각 표본 행을 정규화합니다. PyTorch는 기본 dim=1이며 TensorFlow는 axis를 지정하지 않으면 입력 전체를 하나의 벡터로 봅니다. 라이브러리를 바꿀 때 기본값을 그대로 옮기면 안 됩니다.
norm·ord·p 값
같은 선택을 라이브러리마다 다른 이름으로 표현합니다. scikit-learn은 norm=”l1″, TensorFlow는 ord=1, PyTorch와 ONNX는 p=1을 사용합니다. normalize라는 함수 이름만 보고 L1 방식이라고 판단하지 말고 인자와 기본값을 확인해야 합니다.
eps와 작은 노름
PyTorch의 eps는 노름이 0이거나 매우 작을 때 분모가 지나치게 작아지는 일을 막는 값입니다. 작은 정상 벡터도 eps보다 노름이 작으면 결과의 절댓값 합이 정확히 1이 아닐 수 있습니다. 다른 구현과 결과를 맞추려면 안전값과 적용 규칙을 함께 비교합니다.
영벡터와 빈 표본
모든 성분이 0인 영벡터에는 정규화할 상대적 비중이 없습니다. ONNX는 이 경우 결과를 0으로 정의합니다. 출력이 안전하게 0으로 남더라도 정상 표본과 같은 뜻은 아니므로 빈 문서, 전처리 실패, 미등록 항목인지 원인을 따로 기록해야 합니다.
실전 팁: [3, -1] 같은 정상 벡터와 [0, 0] 영벡터를 함께 넣어 축, 절댓값 합, NaN 발생 여부를 먼저 확인하세요.
헷갈리는 정규화와 무엇이 다른가요?
L2 정규화와 L1 정규화의 차이
L1 정규화는 절댓값의 합으로 나누고 L2 정규화는 제곱합의 제곱근으로 나눕니다. [3, -1]의 L1 결과는 [0.75, -0.25]이지만 L2 결과는 다른 값입니다. 두 방식 모두 양의 스칼라로 나누어 방향을 유지하지만 성분의 크기와 거리 계산에 미치는 영향은 다릅니다.
단순 합계 정규화와 L1 정규화의 차이
단순 합계 정규화는 원래 값의 합으로 나눌 수 있습니다. 음수와 양수가 섞이면 서로 상쇄되어 분모가 0에 가까워질 수 있습니다. L1 정규화는 절댓값을 더하므로 부호가 상쇄되지 않습니다. 값이 모두 0 이상일 때만 두 결과가 같습니다.
L1 규제와 L1 정규화의 차이
L1 규제는 학습 손실에 가중치의 절댓값 크기와 관련된 벌점을 더해 일부 가중치가 0에 가까워지도록 유도하는 방법입니다. L1 정규화는 입력이나 출력 벡터를 노름으로 직접 나누는 전처리 연산입니다. regularization과 normalization은 이름과 목적이 다릅니다.
맨해튼 거리와 L1 정규화의 차이
맨해튼 거리는 두 벡터 성분 차이의 절댓값을 더해 두 점 사이 거리를 계산합니다. L1 정규화는 한 벡터 자체의 절댓값 합으로 그 벡터를 나눕니다. 둘 다 절댓값 합을 사용하지만 하나는 두 점의 거리이고 다른 하나는 벡터의 크기 조정입니다.
확률 정규화와 L1 정규화의 차이
0 이상인 벡터를 L1 정규화하면 값의 합이 1이 되어 확률처럼 보일 수 있습니다. 그러나 음수가 있으면 원래 값의 합은 1이 아닐 수 있고, 입력값에 확률적 의미가 없을 수도 있습니다. 분류 확률을 만들 때 쓰는 소프트맥스와 같은 연산으로 취급하면 안 됩니다.
비교 정리: L1 정규화는 한 벡터의 절댓값 합, L2 정규화는 제곱합의 제곱근, L1 규제는 학습 벌점, 맨해튼 거리는 두 벡터 사이 차이를 다룹니다.
실전에서는 어디에 쓰이나요?
문서의 단어 빈도 특징
문서마다 길이가 다를 때 단어 빈도 벡터를 표본별로 정규화할 수 있습니다. 긴 문서가 단어 수만으로 더 큰 벡터가 되는 영향을 줄이고 각 단어가 문서 안에서 차지하는 상대적 비중을 봅니다. 다만 TF-IDF 같은 다른 가중치와 정규화 순서는 파이프라인 전체에서 고정해야 합니다.
사용자·상품 행동 특징
클릭, 조회, 구매처럼 0 이상인 행동 횟수를 벡터로 만들었다면 전체 활동량보다 행동 구성의 차이를 볼 때 적용할 수 있습니다. 반대로 활동량 자체가 중요한 예측 신호라면 원래 합계를 별도 특징으로 보존하거나 정규화하지 않은 결과와 비교해야 합니다.
희소 행렬 전처리
scikit-learn의 normalize 함수는 배열뿐 아니라 희소 행렬도 받으며 불필요한 복사를 피하려면 CSR 형식을 권장합니다. 0인 항목을 그대로 유지하면서 각 행 또는 열을 단위 노름으로 맞출 수 있어 고차원 희소 특징을 다룰 때 유용합니다.
ONNX 모델 변환과 추론
ONNX LpNormalization 연산자는 p=1과 축을 속성으로 기록합니다. 학습 프레임워크에서 내보낸 뒤 연산자가 유지됐는지, 기본 p=2로 바뀌지 않았는지, 축과 영벡터 출력이 같은지 확인해야 합니다. 변환이 성공했다는 로그만으로 수치 동등성이 보장되지는 않습니다.
실전 팁: 전처리 코드와 모델 그래프 가운데 어디서 L1 정규화를 하는지 한곳으로 정하세요. 양쪽에서 두 번 적용하면 파이프라인 이해와 재현이 어려워집니다.
적용 전후를 어떻게 점검하나요?
1. 입력 모양과 정규화 축을 기록합니다
배치·특징·토큰·채널 차원의 순서와 정규화할 축을 문서에 적습니다. [표본, 특징]과 [특징, 표본]은 같은 숫자를 담아도 axis 의미가 다릅니다. 작은 배치의 행별·열별 결과를 직접 대조하면 축 오류를 빨리 찾을 수 있습니다.
2. 손으로 계산할 예시를 넣습니다
[3, -1]과 [0, 0]을 고정 테스트에 사용합니다. 정상 벡터가 [0.75, -0.25]에 가까운지, 영벡터에서 NaN이나 무한대가 생기지 않는지 봅니다. 음수 부호가 사라졌다면 절댓값 배열을 출력으로 잘못 사용했을 가능성이 있습니다.
3. 출력의 절댓값 합을 확인합니다
0이 아닌 각 벡터에서 출력 성분의 절댓값을 더해 허용 오차 안에서 1인지 검사합니다. 전체 평균만 보면 일부 표본의 축 오류나 영벡터가 가려질 수 있으므로 최솟값·최댓값과 영벡터 개수도 함께 기록합니다.
4. 원래 총량 손실을 평가합니다
정규화 전 벡터의 L1 노름이 업무에 필요한 신호인지 확인합니다. 문서 길이, 사용자 활동량, 센서 신호의 세기처럼 총량이 중요하다면 정규화한 벡터와 함께 원래 노름을 별도 특징으로 보존하는 방식을 검토합니다.
5. 라이브러리와 변환 전후 결과를 대조합니다
PyTorch·TensorFlow·scikit-learn·ONNX에서 같은 입력을 사용해 값과 축별 L1 노름을 비교합니다. p 또는 ord, axis 또는 dim, eps, 자료형, 영벡터 처리 규칙을 따로 적으면 실행 가능한 수치 차이를 찾기 쉽습니다.
한 줄 정리: 입력 축, 손계산 예시, 출력 절댓값 합, 원래 총량의 의미, 변환 전후 수치를 차례로 확인합니다.
사용할 때 무엇을 주의해야 하나요?
첫째, L1 규제와 혼동하지 않습니다. 하나는 벡터를 직접 나누는 연산이고 다른 하나는 학습 손실과 가중치 최적화에 관여합니다. 코드와 문서에 normalization인지 regularization인지 정확히 적습니다.
둘째, 기본 노름을 믿지 않습니다. PyTorch와 ONNX의 기본 p 값, scikit-learn의 기본 norm은 모두 L2입니다. L1이 필요하면 p=1, ord=1, norm=”l1″을 명시하고 결과를 검사합니다.
셋째, 음수가 있는 벡터를 확률로 해석하지 않습니다. 절댓값 합이 1이어도 음수 성분이 남을 수 있습니다. 모든 값이 0 이상이어도 확률의 의미는 데이터와 모델 정의에서 따로 확인해야 합니다.
넷째, 영벡터를 정상 표본처럼 넘기지 않습니다. 0 출력이 안전한 수치 결과일 수는 있어도 유효한 구성 비율을 뜻하지 않습니다. 빈 입력이나 전처리 실패 여부를 따로 표시합니다.
다섯째, 원래 전체량을 지워도 되는지 판단합니다. 정규화 전후의 분류·검색·추천 성능을 같은 검증 데이터로 비교하고 총량이 필요한 경우 원래 L1 노름을 별도 특징으로 남깁니다.
주의: 출력 모양이 맞고 오류가 없다는 사실만 확인하지 말고, 각 표본의 어느 축에서 절댓값 합이 1이 됐는지까지 검증해야 합니다.
자주 묻는 질문
Q1. L1은 무엇을 뜻하나요?
L은 벡터의 크기를 나타내는 노름 표기에서 쓰이며 1은 각 성분의 절댓값을 1제곱한 뒤 더하는 차수를 뜻합니다. 실무에서는 절댓값의 합이라고 이해하면 됩니다.
Q2. L1 정규화 뒤 모든 값의 합이 1이 되나요?
항상 그렇지는 않습니다. 절댓값의 합이 1이 됩니다. 모든 성분이 0 이상이면 값의 합도 1이지만 음수가 섞이면 양수와 음수가 상쇄되어 원래 값의 합은 다를 수 있습니다.
Q3. L1 정규화를 하면 0이 아닌 값이 더 많이 생기나요?
아닙니다. 모든 성분을 같은 양수로 나누므로 0은 그대로 0입니다. 다만 L1 규제는 학습 과정에서 일부 가중치를 0에 가깝게 만드는 효과를 낼 수 있어 두 개념을 구분해야 합니다.
Q4. 영벡터도 절댓값 합이 1이 되나요?
아닙니다. 영벡터의 L1 노름은 0이라 정상적으로 나눌 수 없습니다. ONNX는 출력을 0으로 정의하고 PyTorch는 eps를 사용합니다. 사용하는 라이브러리의 규칙과 빈 입력 처리 방법을 확인해야 합니다.
Q5. L1과 L2 정규화 중 무엇이 더 좋은가요?
항상 더 좋은 한 가지 방식은 없습니다. L1은 절댓값 합과 상대적 몫이 중요한 상황에, L2는 유클리드 길이와 각도 기반 비교에 자주 쓰입니다. 모델과 데이터에 맞춰 검증 성능, 희소성, 거리 계산 방식을 함께 비교합니다.
출처
마무리
L1 정규화는 벡터 성분의 절댓값 합으로 각 값을 나누어 0이 아닌 결과의 절댓값 합을 1로 만드는 연산입니다. 값의 부호와 0인 위치는 유지하면서 표본별 전체 크기를 맞추므로 희소 특징과 상대적 구성 비율을 다루는 AI 전처리에서 쓸 수 있습니다.
실전에서는 네 가지만 기억하면 됩니다. L1 규제와 구분하고 정규화 축과 p·ord·norm 값을 명시하며 영벡터를 따로 다루고 원래 총량을 지워도 되는지 검증하세요. 모델을 다른 라이브러리나 ONNX로 옮길 때는 같은 고정 입력으로 절댓값 합과 출력값을 함께 대조해야 안전합니다.
