2020.10.12-2020.10.18工作周报

摘要

本周主要做了一下四项工作:

  • 跑鱼目论文的代码
  • 吴恩达深度学习课程第三周
  • 《视觉slam十四讲》第三讲、第四讲
  • 读MICCAI上那篇手术机器人论文

一、读鱼目论文的代码,看能读懂多少

环境配好,跑起来了。过程中的三张截图如下:

请添加图片描述
请添加图片描述
请添加图片描述
运行完成之后,窗口全部关闭,生成了一个MKFTrajectory.txt文档,不知道是用来干嘛的。Readme下面提示说:Important: To evaluate the trajectory you will need to transform the result into the rigid body coordinate system. The transformation matrix MCS_to_Rigid_body can be found here. 下载了那个转换矩阵之后,还没明白怎么用的,不知道怎么把这个结果转换到rigid body corrdinate system。。

二、吴恩达的深度学习课程第三周

第三周的课程主要讲了有一层隐藏层的人工神经网络。比第二周Logistic回归更加复杂。实现了具有一个隐藏层的平面数据分类的神经网络。
代码整理如下:

1. Packages

#package imports
import numpy as np
import matplotlib.pyplot as plt
from testCases_v2 import *  # 这是Coursera平台自带的
import sklearn
import sklearn.datasets
import sklearn.linear_model
from planar_utils import plot_decision_boundary, sigmoid, load_planar_dataset,load_extra_datasets  # 这些也是Coursera自带的

%matplotlib inline

np.random.seed(1) # set a seed so that the results are consistent

2. Dataset

First, let’s get the dataset you will work on. The following code will load a “flower” 2-class dataset into variables X and Y.

X, Y = load_planar_dataset()

将这个数据集可视化:

# visualize the data
plt.scatter(X[0,:], X[1,:], c=Y, s=40, cmap=plt.com.Spectral);

在这里插入图片描述

3. Simple Logistic Regression

在建立一个完整的神经网络之前,我们先看看使用第二周的Logsitic回归在这个问题上的表现怎么样。

在这里插入图片描述
精确度为47%

4. 神经网络模型

我们的模型如下:
在这里插入图片描述
相关的数学公式:
在这里插入图片描述
注意:通常构建一个神经网络的方法步骤如下:

  1. 定义神经网络的结构(输入层单元,隐藏层单元等)
  2. 初始化模型的参数
  3. 循环迭代:
    • 实现前向传播算法
    • 计算损失
    • 实现反向传播算法获得梯度
    • 更新参数(梯度下降算法)
4.1 定义神经网络的结构
# GRADED FUNCTION: layer_sizes

def layer_sizes(X, Y):
    """
    Arguments:
    X -- input dataset of shape (input size, number of examples)
    Y -- labels of shape (output size, number of examples)
    
    Returns:
    n_x -- the size of the input layer
    n_h -- the size of the hidden layer
    n_y -- the size of the output layer
    """
    ### START CODE HERE ### (≈ 3 lines of code)
    n_x = X.shape[0] # size of input layer
    n_h = 4  # 默认隐藏层4个单元
    n_y = Y.shape[0] # size of output layer
    ### END CODE HERE ###
    return (n_x, n_h, n_y)
4.2 初始化模型的参数
# GRADED FUNCTION: initialize_parameters

def initialize_parameters(n_x, n_h, n_y):
    """
    Argument:
    n_x -- size of the input layer
    n_h -- size of the hidden layer
    n_y -- size of the output layer
    
    Returns:
    params -- python dictionary containing your parameters:
                    W1 -- weight matrix of shape (n_h, n_x)
                    b1 -- bias vector of shape (n_h, 1)
                    W2 -- weight matrix of shape (n_y, n_h)
                    b2 -- bias vector of shape (n_y, 1)
    """
    
    np.random.seed(2) # we set up a seed so that your output matches ours although the initialization is random.
    
    ### START CODE HERE ### (≈ 4 lines of code)
    W1 = np.random.randn(n_h, n_x) * 0.01
    b1 = np.zeros((n_h, 1))
    W2 = np.random.randn(n_y, n_h) * 0.01
    b2 = np.zeros((n_y, 1))
    ### END CODE HERE ###
    
    assert (W1.shape == (n_h, n_x))
    assert (b1.shape == (n_h, 1))
    assert (W2.shape == (n_y, n_h))
    assert (b2.shape == (n_y, 1))
    
    parameters = {"W1": W1,
                  "b1": b1,
                  "W2": W2,
                  "b2": b2}
    
    return parameters
4.3 循环迭代

前向传播

# GRADED FUNCTION: forward_propagation

def forward_propagation(X, parameters):
    """
    Argument:
    X -- input data of size (n_x, m)
    parameters -- python dictionary containing your parameters (output of initialization function)
    
    Returns:
    A2 -- The sigmoid output of the second activation
    cache -- a dictionary containing "Z1", "A1", "Z2" and "A2"
    """
    # Retrieve each parameter from the dictionary "parameters"
    ### START CODE HERE ### (≈ 4 lines of code)
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]
    ### END CODE HERE ###
    
    # Implement Forward Propagation to calculate A2 (probabilities)
    ### test
    #print(W1.shape)
    #print(X.shape)
    #print(b1.shape)
    #print(W2.shape)
    #print(b2.shape)
    
    ### START CODE HERE ### (≈ 4 lines of code)
    Z1 = np.matmul(W1, X) + b1  # W1: (n_h, n_x) X: (n_x, m)   Z1:(n_h, m)
    A1 = np.tanh(Z1) # A1: (n_h, m)
    Z2 = np.matmul(W2, A1) + b2 # W2:(n_y, n_h)  b2:(n_y, 1)   Z2: (n_y, m)
    A2 = sigmoid(Z2)   # A2:(n_y, m)
    ### END CODE HERE ###
    
    assert(A2.shape == (1, X.shape[1]))
    
    cache = {"Z1": Z1,
             "A1": A1,
             "Z2": Z2,
             "A2": A2}
    
    return A2, cache

计算loss

# GRADED FUNCTION: compute_cost

def compute_cost(A2, Y, parameters):
    """
    Computes the cross-entropy cost given in equation (13)
    
    Arguments:
    A2 -- The sigmoid output of the second activation, of shape (1, number of examples)
    Y -- "true" labels vector of shape (1, number of examples)
    parameters -- python dictionary containing your parameters W1, b1, W2 and b2
    [Note that the parameters argument is not used in this function, 
    but the auto-grader currently expects this parameter.
    Future version of this notebook will fix both the notebook 
    and the auto-grader so that `parameters` is not needed.
    For now, please include `parameters` in the function signature,
    and also when invoking this function.]
    
    Returns:
    cost -- cross-entropy cost given equation (13)
    
    """
    
    m = Y.shape[1] # number of example

    # Compute the cross-entropy cost
    ### START CODE HERE ### (≈ 2 lines of code)
    logprobs = np.multiply(np.log(A2),Y) + np.multiply(np.log(1-A2), 1-Y)
    cost = - (1/m) * np.sum(logprobs)
    ### END CODE HERE ###
    
    cost = float(np.squeeze(cost))  # makes sure cost is the dimension we expect. 
                                    # E.g., turns [[17]] into 17 
    assert(isinstance(cost, float))
    
    return cost

反向传播
在这里插入图片描述

# GRADED FUNCTION: backward_propagation

def backward_propagation(parameters, cache, X, Y):
    """
    Implement the backward propagation using the instructions above.
    
    Arguments:
    parameters -- python dictionary containing our parameters 
    cache -- a dictionary containing "Z1", "A1", "Z2" and "A2".
    X -- input data of shape (2, number of examples)
    Y -- "true" labels vector of shape (1, number of examples)
    
    Returns:
    grads -- python dictionary containing your gradients with respect to different parameters
    """
    m = X.shape[1]
    
    # First, retrieve W1 and W2 from the dictionary "parameters".
    ### START CODE HERE ### (≈ 2 lines of code)
    W1 = parameters["W1"]
    W2 = parameters["W2"]
    ### END CODE HERE ###
        
    # Retrieve also A1 and A2 from dictionary "cache".
    ### START CODE HERE ### (≈ 2 lines of code)
    A1 = cache["A1"]
    A2 = cache["A2"]
    ### END CODE HERE ###
    
    # Backward propagation: calculate dW1, db1, dW2, db2. 
    ### START CODE HERE ### (≈ 6 lines of code, corresponding to 6 equations on slide above)
    dZ2 = A2-Y
    dW2 = (1/m)*np.dot(dZ2,A1.T)
    db2 = (1/m)*np.sum(dZ2, axis=1, keepdims=True)
    dZ1 = np.dot(W2.T, dZ2) * (1 - np.power(A1, 2))
    dW1 = (1/m)*np.dot(dZ1, X.T)
    db1 = (1/m)*np.sum(dZ1, axis=1, keepdims=True)
    ### END CODE HERE ###
    
    grads = {"dW1": dW1,
             "db1": db1,
             "dW2": dW2,
             "db2": db2}
    
    return grads

更新参数

# GRADED FUNCTION: update_parameters

def update_parameters(parameters, grads, learning_rate = 1.2):
    """
    Updates parameters using the gradient descent update rule given above
    
    Arguments:
    parameters -- python dictionary containing your parameters 
    grads -- python dictionary containing your gradients 
    
    Returns:
    parameters -- python dictionary containing your updated parameters 
    """
    # Retrieve each parameter from the dictionary "parameters"
    ### START CODE HERE ### (≈ 4 lines of code)
    W1 = parameters["W1"]
    b1 = parameters["b1"]
    W2 = parameters["W2"]
    b2 = parameters["b2"]
    ### END CODE HERE ###
    
    # Retrieve each gradient from the dictionary "grads"
    ### START CODE HERE ### (≈ 4 lines of code)
    dW1 = grads["dW1"]
    db1 = grads["db1"]
    dW2 = grads["dW2"]
    db2 = grads["db2"]
    ## END CODE HERE ###
    
    # Update rule for each parameter
    ### START CODE HERE ### (≈ 4 lines of code)
    W1 = W1 - learning_rate * dW1
    b1 = b1 - learning_rate * db1
    W2 = W2 - learning_rate * dW2
    b2 = b2 - learning_rate * db2
    ### END CODE HERE ###
    
    parameters = {"W1": W1,
                  "b1": b1,
                  "W2": W2,
                  "b2": b2}
    
    return parameters
4.4 整合前面4.1-4.3三个部分
# GRADED FUNCTION: nn_model

def nn_model(X, Y, n_h, num_iterations = 10000, print_cost=False):
    """
    Arguments:
    X -- dataset of shape (2, number of examples)
    Y -- labels of shape (1, number of examples)
    n_h -- size of the hidden layer
    num_iterations -- Number of iterations in gradient descent loop
    print_cost -- if True, print the cost every 1000 iterations
    
    Returns:
    parameters -- parameters learnt by the model. They can then be used to predict.
    """
    
    np.random.seed(3)
    n_x = layer_sizes(X, Y)[0]
    n_y = layer_sizes(X, Y)[2]
    
    # Initialize parameters
    ### START CODE HERE ### (≈ 1 line of code)
    parameters = initialize_parameters(n_x, n_h, n_y)
    ### END CODE HERE ###
    
    # Loop (gradient descent)

    for i in range(0, num_iterations):
         
        ### START CODE HERE ### (≈ 4 lines of code)
        # Forward propagation. Inputs: "X, parameters". Outputs: "A2, cache".
        A2, cache = forward_propagation(X, parameters)
        
        # Cost function. Inputs: "A2, Y, parameters". Outputs: "cost".
        cost = compute_cost(A2, Y, parameters)
 
        # Backpropagation. Inputs: "parameters, cache, X, Y". Outputs: "grads".
        grads = backward_propagation(parameters, cache, X, Y)
 
        # Gradient descent parameter update. Inputs: "parameters, grads". Outputs: "parameters".
        parameters = update_parameters(parameters, grads)
        
        ### END CODE HERE ###
        
        # Print the cost every 1000 iterations
        if print_cost and i % 1000 == 0:
            print ("Cost after iteration %i: %f" %(i, cost))

    return parameters
4.5 预测
# GRADED FUNCTION: predict

def predict(parameters, X):
    """
    Using the learned parameters, predicts a class for each example in X
    
    Arguments:
    parameters -- python dictionary containing your parameters 
    X -- input data of size (n_x, m)
    
    Returns
    predictions -- vector of predictions of our model (red: 0 / blue: 1)
    """
    
    # Computes probabilities using forward propagation, and classifies to 0/1 using 0.5 as the threshold.
    ### START CODE HERE ### (≈ 2 lines of code)
    A2, cache = forward_propagation(X, parameters)
    predictions = (A2>0.5)
    ### END CODE HERE ###
    
    return predictions
# Build a model with a n_h-dimensional hidden layer
parameters = nn_model(X, Y, n_h = 4, num_iterations = 10000, print_cost=True)

# Plot the decision boundary
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y)
plt.title("Decision Boundary for hidden layer size " + str(4))

# Build a model with a n_h-dimensional hidden layer
parameters = nn_model(X, Y, n_h = 4, num_iterations = 10000, print_cost=True)

# Plot the decision boundary
plot_decision_boundary(lambda x: predict(parameters, x.T), X, Y)
plt.title("Decision Boundary for hidden layer size " + str(4))

输出:
在这里插入图片描述
精度为:98%

三、《视觉slam十四讲》——第三讲 三维空间刚体运动

本节目标:理解三维空间的刚体运动描述方式:旋转矩阵、变换矩阵、四元数和欧拉角

3.1 旋转矩阵

3.1.1 点和向量,坐标系

可以用外积表示向量的旋转。考虑两个不平行的向量 a \mathbf{a} a, b \mathbf{b} b,我们要描述 a \mathbf{a} a b \mathbf{b} b之间是如何旋转的。我们可以用一个向量来描述三维空间中两个向量的旋转关系。在右手法则下,我们用右手的四个指头从 a \mathbf{a} a转向 b \mathbf{b} b,其大拇指朝向就是旋转向量的方向,事实上也是 a × b \mathbf{a}×\mathbf{b} a×b的方向。它的大小由 a \mathbf{a} a b \mathbf{b} b的夹角决定。通过这种方式,我们构造了从 a \mathbf{a} a b \mathbf{b} b的一个旋转向量。这个向量同样位于三维空间中,在此坐标系下,可以用三个实数来描述它。
在这里插入图片描述

3.1.2 坐标系间的欧式变换

与向量间的旋转类似,我们同样可以描述两个坐标系之间的旋转关系,再加上平移,统称为坐标系之间的变换关系。在机器人运动过程中,常见的做法是设定一个惯性坐标系(或者叫世界坐标系),可以认为它是固定不动的。同时,相机或机器人则是一个移动坐标系。我们会问:相机视野中某个向量 p \mathbf{p} p,它的坐标为 p c p_c pc,而从世界坐标系下看,它的坐标是 p w p_w pw。这两个坐标之间是如何转换的呢?这时,就需要先得到该点针对机器人坐标系坐标值,再根据机器人位姿转换到世界坐标系中,这个转换关系由一个矩阵 T T T来描述,如图3-2所示。
.在这里插入图片描述

相机运动是一个刚体运动,它保证了同一个向量在各个坐标系下的长度和夹角都不会发生变化。这种变换称为欧式变换。一个欧式变换一般由一个旋转和一个平移两部分组成。首先来考虑旋转。我们设某个单位正交基 ( e 1 , e 2 , e 3 ) \begin{pmatrix} e_1,e_2,e_3 \end{pmatrix} (e1,e2,e3)经过一次旋转,变成了 ( e 1 ′ , e 2 ′ , e 3 ′ ) \begin{pmatrix}e'_1,e'_2,e'_3\end{pmatrix} (e1,e2,e3)。那么,对于同一个向量 a \mathbf{a} a(注意该向量并没有随着坐标系的旋转而发生改动),它在两个坐标系下的坐标为 [ a 1 , a 2 , a 3 ] T \begin{bmatrix}a_1,a_2,a_3\end{bmatrix}^T [a1,a2,a3]T [ a 1 ′ , a 2 ′ , a 3 ′ ] T \begin{bmatrix}a'_1,a'_2,a'_3\end{bmatrix}^T [a1,a2,a3]T。根据坐标的定义,有:
[ e 1 , e 2 , e 3 ] [ a 1 a 2 a 3 ] = [ e 1 ′ , e 2 ′ , e 3 ′ ] [ a 1 ′ a 2 ′ a 3 ′ ] ( 3.4 ) \begin{bmatrix}e_1,e_2,e_3\end{bmatrix} \begin{bmatrix} a_1\\a_2\\a_3\end{bmatrix} = \begin{bmatrix}e'_1,e'_2,e'_3\end{bmatrix} \begin{bmatrix}a'_1\\a'_2\\a'_3\end{bmatrix}\quad(3.4) [e1,e2,e3]a1a2a3=[e1,e2,e3]a1a2a3(3.4)
为了描述两个坐标之间的关系,我们对上面等式左右同时左乘 [ e 1 T e 2 T e 3 T ] \begin{bmatrix}e^T_1\\e^T_2\\e^T_3 \end{bmatrix} e1Te2Te3T,那么左边的系数变成了单位矩阵,所以:
在这里插入图片描述
我们把中间的矩阵拿出来,定义成一个矩阵 R R R。这个矩阵由两组基之间的内积组成,刻画了旋转前后同一个向量的坐标变换关系。只要旋转是一样的,那么这个矩阵也是一样的。可以说,矩阵 R R R描述了旋转本身。因此它又称为旋转矩阵

旋转矩阵有一些特别的性质。事实上,它是一个行列式为1的正交矩阵。反之,行列式为1的正交矩阵也是一个旋转矩阵。所以,我们可以把旋转矩阵的集合定义如下:
S O ( n ) = { R ∈ R n × n ∣ R R T = I , d e t ( R ) = 1 } (3.6) SO(n)=\{R\in\mathbb{R}^{n\times n}|RR^T=I,det(R)=1\} \quad \text{(3.6)} SO(n)={RRn×nRRT=I,det(R)=1}(3.6)
S O ( n ) SO(n) SO(n)是特殊正交群(Special Orthogonal Group)的意思。这个集合由n维空间的旋转矩阵组成,特别的,SO(3)就是三维空间的旋转矩阵。通过旋转矩阵,我们可以直接谈论两个坐标系之间的旋转变换,而不用再从基开始谈起了。换句话说,旋转矩阵可以描述相机的旋转

由于旋转矩阵为正交阵,它的逆(即转置)描述了一个相反的旋转。按照上面的定义方式,有:
a ′ = R − 1 a = R T a . (3.7) \mathbf{a}'=R^{-1}\mathbf{a}=R^{T}\mathbf{a}.\quad \text{(3.7)} a=R1a=RTa.(3.7)
显然 R T R^{T} RT刻画了一个相反的旋转

在欧式变换中,除了旋转之外还有一个平移。考虑世界坐标系中的向量 a \mathbf{a} a,经过一次旋转(用 R R R描述)和一次平移 t \mathbf{t} t后,得到了 a ′ \mathbf{a}' a,那么把旋转和平移合到一起,有:
a ′ = R a + t . (3.8) \mathbf{a}'=R\mathbf{a}+\mathbf{t}.\quad \text{(3.8)} a=Ra+t.(3.8)
其中, t \mathbf{t} t称为平移向量。通过上式,我们用一个旋转矩阵 R R R和一个平移向量 t \mathbf{t} t完整地描述了一个欧式空间的坐标变换关系。

3.1.3 变换矩阵与齐次坐标

式(3.8)完整地表达了欧式空间的旋转与平移,不过还存在一个小问题:这里的变换关系不是一个线性关系。这样的形式在变换多次后会过于复杂。因此,我们要引入齐次坐标和变换矩阵重写式(3.8):
在这里插入图片描述
这是一个数学技巧:我们把一个三维向量的末尾添加 1 1 1,变成了四维向量,称为齐次坐标。对于这个四维向量,我们可以把旋转和平移写在一个矩阵里面,使得整个关系变成了线性关系。该式中,矩阵 T T T称为变换矩阵(Transform Matrix)

关于变换矩阵 T T T,它具有比较特别的结构:左上角为旋转矩阵,右侧为平移向量,左下角为 0 \mathbf{0} 0向量,右下角为 1 1 1。这种矩阵又称特殊欧式群(Special Euclidean Group):
S E ( 3 ) = { T = [ R t 0 T 1 ] ∈ R 4 × 4 ∣ R ∈ S O ( 3 ) , t ∈ R 3 } . (3.12) SE(3) = \{T=\begin{bmatrix}R&t\\ \mathbf{0}^T & 1 \end{bmatrix} \in \mathbb{R}^{4\times 4} | R \in SO(3), \mathbf{t} \in \mathbb{R}^3 \}. \quad \text{(3.12)} SE(3)={T=[R0Tt1]R4×4RSO(3),tR3}.(3.12)
与SO(3)一样,求解该矩阵的逆表示一个反向的变换:
T − 1 = [ R T R T t 0 T 1 ] . (3.13) T^{-1}=\begin{bmatrix}R^T &R^T\mathbf{t} \\ \mathbf{0}^T & 1\end{bmatrix}. \quad \text{(3.13)} T1=[RT0TRTt1].(3.13)

回顾一下这部分的内容:首先,我们说了向量和它的坐标表示,并介绍了向量间的运算;然后,坐标系之间的运动由欧式变换描述,它由平移和旋转组成。旋转可以由旋转矩阵 S O ( 3 ) SO(3) SO(3)描述,而平移直接由一个 R 3 \mathbb{R}^3 R3向量描述。最后,如果将平移和旋转放在一个矩阵中,就形成了变换矩阵 S E ( 3 ) SE(3) SE(3)

3.2 实践:Eigen

Eigen是一个C++开源线性代数库。它提供了快速的有关矩阵的线性代数运算,还包括解方程等功能。本节学习了如何使用Eigen来表示矩阵、向量,随后引申至旋转矩阵和变换矩阵的计算。

3.3 旋转向量和欧拉角

3.4 四元数

通过对上面小节的学习,基本了解了刚体运动在空间中的位姿变换。3.3和3.4节有点深奥~,暂时先不读了,等下周或者将来用到时再回过头来看吧。

四、读MICCAI的那篇手术机器人论文——机器人辅助微创手术中的实时立体重建

这是一篇比较短的论文,主要内容总结如下:
这篇论文主要提出了一种新颖的立体重建算法,该算法在一组候选特征匹配周围传播视差信息。这具有避免镜面高光,仪器遮挡以及与视图有关的照明偏差的问题。此外,该算法可以与允许深度分布在非常分散的视图中传播的任何特征匹配策略一起使用。为具有已知几何体的幻影模型提供了验证,该数据可在线获得,以便在现场建立结构化验证方案。通过在机器人辅助程序的各种体内图像上进行重建,进一步证明了所提出方法的实用价值,这些方法也可供社区使用。

篇末总结了该方法的优劣。为了在体内图像上定性评估所提出方法的性能,本文使用了使用daVinci®手术系统从不同手术程序中获取的几个数据集。 视差图的结果和相应的重建3D渲染结果如下图所示。很明显,所提出的技术有效地捕获了手术部位的3D几何形状。 它很好地解决了由于手术器械而导致的较大视差不连续以及镜面反射较大的问题。 但是,存在一些错误,尤其是在遮挡边界处,需要进一步解决。 重要的是要注意,本文没有明确地迎合镜面反射或模型遮挡,例如通过使用检测,并且没有采用任何手术器械跟踪。 通过将这种策略纳入本文的方法,应该可以显着改善结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值