2015-07-03 21 views
9

Tôi có một tập hợp dữ liệu mô phỏng nơi tôi muốn tìm độ dốc thấp nhất trong các tham số n. Khoảng cách của dữ liệu là không đổi theo từng chiều, nhưng không phải tất cả như nhau (tôi có thể thay đổi điều đó vì lợi ích của sự đơn giản).đạo hàm bậc hai của mảng thứ hai

Tôi có thể sống với một số thiếu chính xác về số, đặc biệt là đối với các cạnh. Tôi rất muốn không tạo ra một spline và sử dụng đạo hàm đó; chỉ trên các giá trị thô sẽ là đủ.

Có thể tính toán đạo hàm đầu tiên với numpy sử dụng hàm numpy.gradient().

import numpy as np 

data = np.random.rand(30,50,40,20) 
first_derivative = np.gradient(data) 
# second_derivative = ??? <--- there be kudos (: 

Đây là một lời nhận xét về Laplace so với ma trận Hessian; đây không phải là một câu hỏi nữa mà là để giúp hiểu biết về độc giả trong tương lai.

Tôi sử dụng làm testcase một hàm 2D để xác định khu vực 'phẳng nhất' bên dưới ngưỡng. Những hình ảnh sau đây cho thấy sự khác biệt trong kết quả giữa việc sử dụng tối thiểu là second_derivative_abs = np.abs(laplace(data)) và tối thiểu các nội dung sau:

second_derivative_abs = np.zeros(data.shape) 
hess = hessian(data) 
# based on the function description; would [-1] be more appropriate? 
for i in hess[0]: # calculate a norm 
    for j in i[0]: 
     second_derivative_abs += j*j 

Thang màu mô tả các giá trị chức năng, các mũi tên miêu tả đạo hàm đầu tiên (gradient), dấu chấm đỏ điểm gần bằng không nhất và đường màu đỏ ngưỡng.

Chức năng máy phát cho dữ liệu là (1-np.exp(-10*xi**2 - yi**2))/100.0 với xi, yi được tạo với np.meshgrid.

Laplace:

laplace solution

Hessian:

hessian solution

+1

Tôi tự hỏi; Tôi chỉ quan tâm đến độ lớn của độ dốc, không quá nhiều hướng.Có thể nó là đủ nếu tôi tính toán gradient trên tổng của các mục nhập danh sách dẫn xuất tuyệt đối đầu tiên? 'second_derivative = np.gradient (tổng ([df * df cho d trong first_derivative]))' (với 'sum' bảo tồn hình dạng vì lợi ích của đối số) – Faultier

+0

Được rồi, tôi nghĩ rằng tôi hiểu những gì bạn muốn bây giờ. Bạn chỉ muốn có được vùng phẳng nhất, hoặc bất cứ điều gì "phẳng nhất" có nghĩa là trong không gian N. Tôi cố gắng không sử dụng một số dẫn xuất thứ hai chút nào, nhưng tính toán độ dốc tuyệt đối ở tất cả các điểm (tổng các bình phương của kích thước đầu tiên của kết quả 'np.gradient', như bạn đã nói trong bình luận của bạn), và sau đó tìm vùng ngưỡng từ đó, và tìm mức tối thiểu bên trong vùng ngưỡng (nếu bạn hoạt động đủ phức tạp, việc tìm kiếm minima toàn cầu có thể thực sự khó). Tôi sẽ thử xung quanh một chút và đăng một câu trả lời khác nếu tôi tìm thấy một cái gì đó. – Carsten

+0

@Carsten Tổng của tất cả các gradient sẽ không mang lại vùng phẳng nhất; trong hình ảnh trường hợp thử nghiệm này nó sẽ mang lại trung tâm của 2d gaussian. điều này là do không có nghĩa là khu vực phẳng nhất. Vì vậy tôi nghĩ rằng nó cần phải được thực hiện với các dẫn xuất 2 propper thay vì đầu tiên. – Faultier

Trả lời

9

Các đạo hàm bậc hai được đưa ra bởi các Hessian matrix. Đây là một thực hiện Python cho mảng ND, mà bao gồm trong việc áp dụng np.gradient hai lần và lưu trữ đầu ra một cách thích hợp,

import numpy as np 

def hessian(x): 
    """ 
    Calculate the hessian matrix with finite differences 
    Parameters: 
     - x : ndarray 
    Returns: 
     an array of shape (x.dim, x.ndim) + x.shape 
     where the array[i, j, ...] corresponds to the second derivative x_ij 
    """ 
    x_grad = np.gradient(x) 
    hessian = np.empty((x.ndim, x.ndim) + x.shape, dtype=x.dtype) 
    for k, grad_k in enumerate(x_grad): 
     # iterate over dimensions 
     # apply gradient again to every component of the first derivative. 
     tmp_grad = np.gradient(grad_k) 
     for l, grad_kl in enumerate(tmp_grad): 
      hessian[k, l, :, :] = grad_kl 
    return hessian 

x = np.random.randn(100, 100, 100) 
hessian(x) 

Lưu ý rằng nếu bạn chỉ quan tâm đến tầm quan trọng của đạo hàm bậc hai, bạn có thể sử dụng Laplace operator thực hiện bởi scipy.ndimage.filters.laplace, là dấu vết (tổng các phần tử đường chéo) của ma trận Hessian.

Lấy phần tử nhỏ nhất của ma trận Hessian có thể được sử dụng để ước tính độ dốc thấp nhất theo bất kỳ hướng không gian nào.

+1

Tôi hiện đang thử nghiệm với cả hai giải pháp được đề xuất trên một testcase 2D (Tôi thích xem xét mọi thứ). Khi nói dốc, tôi có nghĩa là ít nhất trong tất cả các hướng; về cơ bản là khu vực bằng phẳng nhất mà tôi có thể tìm thấy. Có vẻ hứa hẹn cho đến nay, nhưng vẫn có một số thử nghiệm để làm (: – Faultier

+1

Tôi không có không gian để đăng testcase 2D mà không gây ô nhiễm cho câu hỏi, sự khác biệt trong kết quả giữa laplace và hessian có vẻ là chúng mang lại các điểm khác nhau. tối thiểu của laplace hoặc tổng của hình vuông dọc theo 'x.dim, x.ndim' cho hessian.Để hiểu biết của tôi, sau này có các dẫn xuất hỗn hợp vào tài khoản và do đó nên chính xác hơn cho mục đích của tôi? – Faultier

+1

Tôi đã thêm hình ảnh của Trong khi tôi nghĩ rằng cả hai thuật toán làm một công việc tốt, tôi nghĩ rằng tôi sẽ thích hessian và mở rộng nó để stepwidths biến, cũng như thảo luận nó hiện công việc chính xác hơn Edit: Tôi chỉ nhìn thấy chỉnh sửa của bạn trên câu trả lời của bạn, do đó bạn có thể vui lòng xem lại hình ảnh/mã của tôi và cho tôi biết nếu tôi thực sự làm đúng (: – Faultier

1

Bạn có thể thấy ma trận Hessian dưới dạng gradient, nơi bạn áp dụng gradient lần thứ hai cho mỗi thành phần của gradient đầu tiên được tính ở đây là ma trận definig Hessian wikipedia link và bạn có thể thấy rõ ràng đó là độ dốc của gradient , đây là một thực hiện trăn xác định độ dốc sau đó bao bố:

import numpy as np 
#Gradient Function 
def gradient_f(x, f): 
    assert (x.shape[0] >= x.shape[1]), "the vector should be a column vector" 
    x = x.astype(float) 
    N = x.shape[0] 
    gradient = [] 
    for i in range(N): 
    eps = abs(x[i]) * np.finfo(np.float32).eps 
    xx0 = 1. * x[i] 
    f0 = f(x) 
    x[i] = x[i] + eps 
    f1 = f(x) 
    gradient.append(np.asscalar(np.array([f1 - f0]))/eps) 
    x[i] = xx0 
    return np.array(gradient).reshape(x.shape) 

#Hessian Matrix 
def hessian (x, the_func): 
    N = x.shape[0] 
    hessian = np.zeros((N,N)) 
    gd_0 = gradient_f(x, the_func) 
    eps = np.linalg.norm(gd_0) * np.finfo(np.float32).eps 
    for i in range(N): 
    xx0 = 1.*x[i] 
    x[i] = xx0 + eps 
    gd_1 = gradient_f(x, the_func) 
    hessian[:,i] = ((gd_1 - gd_0)/eps).reshape(x.shape[0]) 
    x[i] =xx0 
    return hessian 

là một kiểm tra, ma trận Hessian của (x^2 + y^2) là 2 * I_2 nơi I_2 là ma trận sắc của không gian 2

Các vấn đề liên quan