美文网首页
Numpy练习(5.16作业)

Numpy练习(5.16作业)

作者: Pessimist_34ad | 来源:发表于2018-05-18 10:21 被阅读0次

    PS: 这次作业还使用到了Scipy库.
    PPS: 由于作业使用的英文, 本次作业我也选择使用英文完成

    Generate a n*m matrix A, with random Gaussian entries, and a m*m matrix B, a Toeplitz matrix, where n = 200, m = 500.

    Preparation

    Code:

    import numpy as np
    from scipy.linalg import toeplitz
    SIZE_N = 200
    SIZE_M = 500
    MU = 0.0
    SIGMA = 1.0
    # random Gaussian entries produce sequence with expectation MU and variance SIGMA.
    
    # Generate matrix with random Gaussian entries
    matrix_a = SIGMA * np.random.randn(SIZE_N, SIZE_M) + MU
    
    # Generate toeplitz matrix
    matrix_b = toeplitz(list(range(1, SIZE_M + 1))[::-1], list(range(1, SIZE_M + 1)[::-1]))
    

    Generated Matrix B:

    array([[500, 499, 498, ...,   3,   2,   1],
           [499, 500, 499, ...,   4,   3,   2],
           [498, 499, 500, ...,   5,   4,   3],
           ...,
           [  3,   4,   5, ..., 500, 499, 498],
           [  2,   3,   4, ..., 499, 500, 499],
           [  1,   2,   3, ..., 498, 499, 500]])
    

    Ex 9-1 Matrix operation

    Quite simple. View comments in the following code:

    #Ex 9-1
    # Compute A+A
    result = matrix_a + matrix_a
    # compute A*(A)^T
    result = np.dot(matrix_a, matrix_a.T)
    # compute (A)^T*A
    result = np.dot(matrix_a.T, matrix_a)
    # compute A*B
    result = np.dot(matrix_a, matrix_b)
    # given lambda, compute A *(B - lambda * I)
    # Attention! lambda is a keyword in python
    def myfun1(A, B, p):
        return np.dot(A, (B - p * np.identity(B.shape[0])))
    

    Ex 9-2 Solving a linear system

    Solve linear systems of equation by the inverse of coefficient matrix:

    # Generate a random vector b
    vector_b = np.random.random((matrix_b.shape[1]))
    # x = B^(-1) * b
    solution = np.linalg.inv(matrix_b).dot(vector_b)
    

    Or you can use function numpy.linalg.solve directly.

    solution = np.linalg.solve(matrix_b, vector_b)
    

    Here is details for numpy.linalg.solve.

    Ex 9-3 Norm

    Also quite simple, view comments in the code below:

    # Compute the Frobenius norm of A
    # Notice that the 2nd param can be None, for it's set to get Frobenius norm for a matrix as default
    frobenius_norm_A = np.linalg.norm(matrix_a, 'fro')
    
    # Compute the infinity norm of B
    # 2nd param cannot be ignored
    infinity_norm_B = np.linalg.norm(matrix_b, np.inf)
    
    # Get the maximum & minimum of B
    max_element_of_B = matrix_b.max()
    min_element_of_B = matrix_b.min()
    

    Ex 9-4 Power iteration

    View Here for the explanation of Power iteration.

    Here I write a function power_iterationt(A, error) which computes the approximate largest eigenvalues of a given matrix A. The max error of eigenvalues will not exceed error. The function will return the largest eigenvalue, the corresponding eigenvector of A, and it's iteration times.

    # function to compute eigenvalue with Power Iteration
    def power_iteration(A, error):
        times = 0   #Iteration count
        last_eig = 1.0
        new_eig = 0.0
        u = np.random.rand(A.shape[0])
        print(isinstance(last_eig, float))
        while (times == 0 or abs(last_eig - new_eig) > error): #stopping condition
            last_eig = new_eig
            v = A.dot(u)
            new_eig = abs(v.max()) 
            u = v / new_eig  #normalize the vector, it's a key part for power iteration.
            times = times + 1
        return new_eig, u, times
    

    And I test the iteration times given different matrix sizes(10, 100, 500, 1000, 2000, 10000):

    error = 0.0001
    for i in [10, 100, 500, 1000, 2000, 10000]:
        A = np.random.rand(i, i)
        print("SIZE = %d, Iteration times = %d" % (i, power_iteration(A, error)[2]))
    

    One of the test results are:

    SIZE = 10, Iteration times = 8
    SIZE = 100, Iteration times = 6
    SIZE = 500, Iteration times = 6
    SIZE = 1000, Iteration times = 6
    SIZE = 2000, Iteration times = 5
    SIZE = 10000, Iteration times = 6
    

    No apparent differences on iteration timesare shown with different size of matrix.

    And I use time.clock() to compare computation time when given different size of matrix:

    error = 0.0001
    for i in [10, 100, 500, 1000, 2000, 10000]:
        A = np.random.rand(i, i)
        start = time.clock()
        power_iteration(A, error)
        end = time.clock()
        print("SIZE = %d, computation time = %fs" % (i, end - start))
    

    One of the test results is:

    SIZE = 10, computation time = 0.000109s
    SIZE = 100, computation time = 0.000394s
    SIZE = 500, computation time = 0.008850s
    SIZE = 1000, computation time = 0.025489s
    SIZE = 2000, computation time = 0.057395s
    SIZE = 10000, computation time = 1.431594s
    

    It seems that the running time is not proportional to the matrix size. The relation between them needs more analysis.

    Ex 9-5

    # Size of Matrix C
    n = 10
    
    def random_zero_or_one(p):
        return (float)(np.random.random() > 1-p)
    
    matrix_c = np.array(list(map(random_zero_or_one, [0.5] * n * n))).reshape((n, n))
    # SVD factorization
    U, s, Vh = scipy.linalg.svd(matrix_c)
    print(s)
    

    And I test the singular value of C given different n and p:

    for n in list(range(2, 100, 5)):
        average = 0
        p = np.random.random()
        for test_times in range(10):
            matrix_c = np.array(list(map(random_zero_or_one, [p] * n * n))).reshape((n, n))
            U, s, Vh = scipy.linalg.svd(matrix_c)
            average = average +s.max()
        average = average / 10
        print("singular value: %f, p = %f, n = %d, p*n = %f" % (average, p, n, p*n)) 
    

    Results:

    singular value: 1.123607, p = 0.355978, n = 2, p*n = 0.711957
    singular value: 2.318768, p = 0.231591, n = 7, p*n = 1.621135
    singular value: 2.286219, p = 0.112528, n = 12, p*n = 1.350333
    singular value: 16.922299, p = 0.995744, n = 17, p*n = 16.927640
    singular value: 12.941962, p = 0.573954, n = 22, p*n = 12.626985
    singular value: 17.642513, p = 0.646745, n = 27, p*n = 17.462121
    singular value: 25.088633, p = 0.777588, n = 32, p*n = 24.882804
    singular value: 21.929907, p = 0.581553, n = 37, p*n = 21.517446
    singular value: 33.011162, p = 0.781029, n = 42, p*n = 32.803204
    singular value: 13.905496, p = 0.279924, n = 47, p*n = 13.156423
    singular value: 13.855356, p = 0.250213, n = 52, p*n = 13.011097
    singular value: 55.627474, p = 0.974140, n = 57, p*n = 55.525976
    singular value: 3.424217, p = 0.036468, n = 62, p*n = 2.261025
    singular value: 64.438280, p = 0.960761, n = 67, p*n = 64.370955
    singular value: 35.216698, p = 0.477921, n = 72, p*n = 34.410340
    singular value: 61.532490, p = 0.794089, n = 77, p*n = 61.144878
    singular value: 23.501740, p = 0.276596, n = 82, p*n = 22.680886
    singular value: 26.268507, p = 0.294773, n = 87, p*n = 25.645271
    singular value: 55.765074, p = 0.603855, n = 92, p*n = 55.554649
    singular value: 4.250828, p = 0.031018, n = 97, p*n = 3.008710
    

    The max singular value may be the product of p and n

    Ex 9-6

    Method:
    First construct a array B with the same size of A, where each entries are z.
    Then find the minimum absolute value of B - A with function numpy.argmin, which return the index.
    Lastly index the entry in A.

    def get_nearest_neighbor(z, a):
    # print info of z and A
        print("z = %f" % z)
        print("A = ")
        print(a)
    # return the answer
        return a[np.argmin(abs(a-z))]
    
    # test code
    # randomly generate z and A
    z = np.random.rand()
    a = np.random.rand(10)
    print(get_nearest_neighbor(z, a))
    

    相关文章

      网友评论

          本文标题:Numpy练习(5.16作业)

          本文链接:https://www.haomeiwen.com/subject/sbpwdftx.html