벡터 연산에 기초한 확률 적 경사 하강?


10

N 개의 샘플이있는 데이터 세트를 사용하여 확률 적 경사 하강 회귀 알고리즘을 훈련시키고 싶다고 가정 해 봅시다. 데이터 세트의 크기가 고정되어 있으므로 데이터를 T 번 재사용합니다. 각 반복 또는 "에포크"에서 전체 트레이닝 세트를 무작위로 재정렬 한 후 각 트레이닝 샘플을 정확히 한 번 사용합니다.

내 구현은 Python과 Numpy를 기반으로합니다. 따라서 벡터 연산을 사용하면 계산 시간이 크게 단축 될 수 있습니다. 배치 그라디언트 디센트의 벡터화 된 구현을 생각해내는 것은 매우 간단합니다. 그러나 확률 구배 하강의 경우 각 시대에서 모든 샘플을 반복하는 외부 루프를 피하는 방법을 알 수 없습니다.

확률 구배 하강의 벡터화 구현을 아는 사람이 있습니까?

편집 : 내 데이터 세트의 크기가 고정 된 경우 왜 온라인 그라디언트 디센트를 사용하고 싶은지 묻습니다.

[1]에서 온라인 그라디언트 디센트는 배치 그라디언트 디센트보다 경험적 비용의 최소로 느리게 수렴됨을 알 수 있습니다. 그러나 예상 비용의 최소 수준으로 더 빨리 수렴되어 일반화 성능을 측정합니다. 교차 검증을 통해 특정 문제에서 이러한 이론적 결과의 영향을 테스트하고 싶습니다. 벡터화 된 구현이 없으면 온라인 그라디언트 디센트 코드가 배치 그라디언트 디센트 코드보다 훨씬 느립니다. 이는 교차 검증 프로세스가 완료되는 데 걸리는 시간을 크게 증가시킵니다.

편집 : ffriend의 요청에 따라 온라인 그라데이션 하강 구현의 의사 코드를 여기에 포함시킵니다. 회귀 문제를 해결하고 있습니다.

Method: on-line gradient descent (regression)
Input: X (nxp matrix; each line contains a training sample, represented as a length-p vector), Y (length-n vector; output of the training samples)
Output: A (length-p+1 vector of coefficients)

Initialize coefficients (assign value 0 to all coefficients)
Calculate outputs F
prev_error = inf
error = sum((F-Y)^2)/n
it = 0
while abs(error - prev_error)>ERROR_THRESHOLD and it<=MAX_ITERATIONS:
    Randomly shuffle training samples
    for each training sample i:
        Compute error for training sample i
        Update coefficients based on the error above
    prev_error = error
    Calculate outputs F
    error = sum((F-Y)^2)/n
    it = it + 1

[1] "대규모 온라인 학습", L. Bottou, Y. Le Cunn, NIPS 2003.


2
데이터 집합을 미니 배치로 분할하고 모델을 각 미니 배치에 순차적으로 맞 춥니 다.
ffriend

@ffriend 감사합니다. 그러나 순수한 온라인 구현은 아닙니다.
Pablo Suau

1
데이터 세트가 고정 된 경우 "순수한 온라인"구현을 사용하는 이유는 무엇입니까? SGD는 전체 데이터 세트를 한 번에 반복 할 필요는 없지만 임의의 수의 조각 (미니 배치)으로 분할하여 하나씩 처리 할 수 ​​있다고 말합니다. 크기 1의 미니 배치는 예를 들어 트위터 피드와 같이 지속적이고 끝이없는 데이터 소스가 있고 각각의 새로운 관측 후 모델을 업데이트하려는 경우에만 의미가 있습니다. 그러나 매우 드문 경우이며 고정 데이터 세트에는 해당되지 않습니다.
ffriend

매우 늦은 답변에 대해 사과드립니다. 원래 질문에 추가 한 텍스트를 확인하십시오.
Pablo Suau

1
구현을 보여줄 수 있습니까? 오해가 있지만 코드 샘플이 없으면 설명하기가 어렵습니다.
ffriend

답변:


10

우선, 단어 "sample"은 일반적으로 모집단의 하위 집합 을 설명하는 데 사용 되므로 "example"과 같은 것을 참조합니다.

이 줄 때문에 SGD 구현이 느립니다.

for each training example i:

여기서는 모델 매개 변수의 각 업데이트에 대해 정확히 하나의 예제를 사용합니다. 정의에 따르면 벡터화는 한 요소의 연산을 해당 요소의 벡터 연산으로 변환하는 기술입니다. 따라서 아니요, 예제를 하나씩 처리 할 수 ​​없으며 여전히 벡터화를 사용할 수 있습니다.

그러나 미니 배치 를 사용하여 실제 SGD에 근접 할 수 있습니다 . 미니 배치는 원본 데이터 세트의 작은 하위 집합입니다 (예 : 100 개 예). 미니 배치를 기반으로 오류 및 매개 변수 업데이트를 계산하지만, 전체 최적화 없이도 많은 오류를 반복하여 프로세스를 확률 적으로 만듭니다. 따라서 구현 속도를 높이려면 이전 줄을 다음과 같이 변경하면 충분합니다.

batches = split dataset into mini-batches
for batch in batches: 

단일 예제가 아닌 배치에서 오류를 계산합니다.

꽤 명백하지만, 예제 수준별로 벡터화도 언급해야합니다. 즉, 이와 같은 대신 :

theta = np.array([...])  # parameter vector
x = np.array([...])      # example
y = 0                    # predicted response
for i in range(len(example)):
    y += x[i] * theta[i]
error = (true_y - y) ** 2  # true_y - true value of response

반드시 다음과 같이해야합니다.

error = (true_y - sum(np.dot(x, theta))) ** 2

미니 배치를 위해 일반화하기가 쉽습니다.

true_y = np.array([...])     # vector of response values
X = np.array([[...], [...]]) # mini-batch
errors = true_y - sum(np.dot(X, theta), 1)
error = sum(e ** 2 for e in errors)

1
나는 이것이 갈 길이라고 생각합니다. 잘 선택된 크기의 미니 배치는 실제로 배치 또는 온라인 버전보다 빠르게 수렴 할 수 있습니다 (이전 세트는 전체 세트당 한 번만 가중치를 업데이트하고 후자는 벡터화 할 수 없으며 추가 가중치 업데이트 단계가 더 자주 있음)
Neil Slater

둘 다 감사합니다. 미니 배치를 완고 히 거부 한 것에 대해 사과했지만 수렴 속도에이 방법이 어떤 영향을 미치는지 확신 할 수 없었습니다. 닐, 당신의 긍정은 당신 자신의 경험에서 나왔습니까?
Pablo Suau

1
@PabloSuau 10 주 코스 라에서 Andrew Ng의 머신 러닝 수업을 확인할 수 있는데, 왜 수렴이 SGD와 배치 GD보다 빠를 수 있는지 설명합니다. 더 정확하게 말하면 항상 SGD만큼 빠르지 만 실제로는 더 빠를 수도 있습니다.
gaborous

1

scikit SGD 분류기의 partial_fit 메소드를 확인하십시오 . 호출하는 것을 제어 할 수 있습니다. 한 번에 인스턴스를 전달하여 온라인 학습을 "실제"로 수행하거나 모든 데이터를 배열로 사용할 수있는 경우 인스턴스를 미니 배치로 배치 할 수 있습니다. 그렇다면 배열을 슬라이스하여 미니 배치를 제공 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.