복붙노트

[PYTHON] Numpy dot은 대칭 곱셈에 대해서 너무 똑똑하다.

PYTHON

Numpy dot은 대칭 곱셈에 대해서 너무 똑똑하다.

이 동작에 대한 설명서는 누구나 알고 있습니까?

import numpy as np
A  = np.random.uniform(0,1,(10,5))
w  = np.ones(5)
Aw = A*w
Sym1 = Aw.dot(Aw.T)
Sym2 = (A*w).dot((A*w).T)
diff = Sym1 - Sym2

diff.max ()는 0이 아닌 기계 정밀도에 가깝습니다. 4.4e-16.

이 (0과의 불일치) 일반적으로 괜찮습니다 ... 유한 정밀도의 세계에서 우리는 놀라지 말아야합니다.

게다가, 나는 대칭이 대칭적인 제품에 대해 현명하다는 것을 추측 할 것이다.

그러나 나는 혼란스러운 시스템을 다루는데,이 작은 불일치는 디버깅 할 때 빠르게 눈에 띄게됩니다. 그래서 나는 정확히 무슨 일이 일어나는지 알고 싶습니다.

해결법

  1. ==============================

    1.이 동작은 끌어 오기 요청 # 6932에서 NumPy 1.11.0에 대해 도입 된 변경 사항의 결과입니다. 1.11.0의 릴리스 노트에서

    이 동작은 끌어 오기 요청 # 6932에서 NumPy 1.11.0에 대해 도입 된 변경 사항의 결과입니다. 1.11.0의 릴리스 노트에서

    해당 홍보에 대한 변경 사항에서이 의견을 찾습니다.

    /*
     * Use syrk if we have a case of a matrix times its transpose.
     * Otherwise, use gemm for all other cases.
     */
    

    따라서 NumPy는 행렬에 대치 된 행의 경우를 명시 적으로 확인하고이 경우 다른 기본 BLAS 함수를 호출합니다. @hpaulj는 주석에 주석을 달았 기 때문에, NumPy에 대한 검사는 저렴합니다. 왜냐하면 2 차원 배열은 거꾸로 된 모양과 스트라이드를 가진 원래 배열의 뷰이기 때문에 배열의 몇 가지 메타 데이터를 검사하기에 충분합니다 ( 실제 배열 데이터를 비교할 필요없이).

    불일치를 보여주는 약간 더 간단한 사례가 있습니다. 도트에 인수 중 하나에 .copy를 사용하면 NumPy의 특수 케이스를 파기에 충분합니다.

    import numpy as np
    random = np.random.RandomState(12345)
    A = random.uniform(size=(10, 5))
    Sym1 = A.dot(A.T)
    Sym2 = A.dot(A.T.copy())
    print(abs(Sym1 - Sym2).max())
    

    이 특별한 케이스의 장점 중 하나는 속도 향상의 확실한 잠재력을 넘어선 것입니다. BLAS 구현에 의존하게 될 것이라고 확신합니다. (실제로는 BLAS 구현에 따라 달라질 수 있습니다.) 완벽한 대칭 결과를 얻으려면 syrk가 사용되는데, 수치 적 오류까지 단순히 대칭 인 행렬이 아니라. 이것에 대한 (아주 좋지 않은) 테스트로서 나는 시도했다.

    import numpy as np
    random = np.random.RandomState(12345)
    A = random.uniform(size=(100, 50))
    Sym1 = A.dot(A.T)
    Sym2 = A.dot(A.T.copy())
    print("Sym1 symmetric: ", (Sym1 == Sym1.T).all())
    print("Sym2 symmetric: ", (Sym2 == Sym2.T).all())
    

    내 컴퓨터의 결과 :

    Sym1 symmetric:  True
    Sym2 symmetric:  False
    
  2. ==============================

    2.나는 이것이 중간 부동 소수점 레지스터를 80 비트 정밀도로 승격시키는 것과 관련이 있다고 생각한다. 이 가설을 어느 정도 확인하는 것은 우리가 더 적은 수레를 사용한다면 우리 결과에서 일관되게 0을 얻는다는 것입니다. ala

    나는 이것이 중간 부동 소수점 레지스터를 80 비트 정밀도로 승격시키는 것과 관련이 있다고 생각한다. 이 가설을 어느 정도 확인하는 것은 우리가 더 적은 수레를 사용한다면 우리 결과에서 일관되게 0을 얻는다는 것입니다. ala

    A  = np.random.uniform(0,1,(4,2))
    w  = np.ones(2)
    Aw = A*w
    Sym1 = Aw.dot(Aw.T)
    Sym2 = (A*w).dot((A*w).T)
    diff = Sym1 - Sym2
    # diff is all 0's (ymmv)
    
  3. from https://stackoverflow.com/questions/43453707/numpy-dot-too-clever-about-symmetric-multiplications by cc-by-sa and MIT license