ARP原理和ARP攻击

[TOC]

ARP(Address Resolution Protocol)地址解析协议,目的是实现IP地址到MAC地址的转换。

在TCP/IP协议栈中,最不安全的协议莫过于ARP了,我们经常听到的网络扫描,内网渗透,流量欺骗等等,他们基本上都与ARP有关系,甚至可以说,他们的底层都是基于ARP实现的。但是ARP的是实现仅需一问一答的两个包即可,实现上很简单。

目录

  • ARP协议
  • ARP数据包信息
  • ARP攻击

一、ARP协议

ARP(Address Resolution Protocol)地址解析协议,目的是实现IP地址到MAC地址的转换。

在计算机间通信的时候,计算机要知道目的计算机是谁(就像我们人交流一样,要知道对方是谁),这中间需要涉及到MAC地址,而MAC是真正的电脑的唯一标识符。

为什么需要ARP协议呢?因为在OSI七层模型中,对数据从上到下进行封装发送出去,然后对数据从下到上解包接收,但是上层(网络层)关心的IP地址,下层关心的是MAC地址,这个时候就需要映射IP和MAC。

ARP之简单请求应答

​ 当两台计算机在同一个局域网通信,我们以ping命令为例,该命令使用的ICMP协议

image-20211028215821598

PC1依据OSI模型①依次从上至下对数据进行封装,包括对ICMP Date加IP包头的封装,但是到了封装MAC地址的时候,②PC1首先查询自己的ARP缓存表,发现没有IP2和他的MAC地址的映射,这个时候MAC数据帧封装失败。我们使用ping命令的时候,是指定PC2的IP2的,计算机是知道目的主机的IP地址,能够完成网络层的数据封装,因为设备通信还需要对方的MAC地址,但是PC1的缓存表里没有,所以在MAC封装的时候填入不了目的MAC地址。

那么PC1为了获取PC2的MAC地址,③PC1要发送询问信息,询问PC2的MAC地址,询问信息包括PC1的IP和MAC地址、PC2的IP地址,这里我们想到一个问题,即使是询问信息,也是需要进行MAC数据帧的封装,那这个询问信息的目的MAC地址填什么呢,规定当目的MAC地址为ff-ff-ff-ff-ff-ff时,就代表这是一个询问信息,也即使后面我要说的广播。

PC2收到这个询问信息后,将这里面的IP1和MAC1(PC1的IP和MAC)添加到本地的ARP缓存表中,然后④PC2发送应答信息,对数据进行IP和MAC的封装,发送给PC1,因为缓存表里已经有PC1的IP和MAC的映射了呢。这个应答信息包含PC2的IP2和MAC2。PC1收到这个应答信息,理所应当的就获取了PC2的MAC地址,并添加到自己的缓存表中。

经过这样交互式的一问一答,PC1和PC2都获得了对方的MAC地址,值得注意的是,目的主机先完成ARP缓存,然后才是源主机完成ARP缓存。之后PC1和PC2就可以真正交流了。

ARP之广播请求单播回应

​ 上图面的图解是不完全的ARP协议,因为在局域网里边不会只有两台主机,这里就要考虑如何在局域网众多主机里获得目的主机的MAC。

blob.png

和上面的一样,刚开始PC1并不知道PC2的MAC地址,同样需要发送ARP请求,但是这个局域网里主机很多,怎么唯独获取PC2的MAC呢,①我们想到和一群陌生人交流一样,可以挨着询问一遍,这就是我们要说的广播,首先PC1广播发送询问信息(信息和上一张图介绍的一样),在这个普通交换机上连接的设备都会受到这个PC1发送的询问信息。

接下来②需要做的是,所有在这个交换机上的设备需要判断此询问信息,如果各自的IP和要询问的IP不一致,则丢弃,如图PC3、Route均丢弃该询问信息,而对于PC2判断该询问信息发现满足一致的要求,则接受,同样的写入PC1的IP和MAC到自己的ARP映射表中。

最后,③PC2单播发送应答信息给PC1,告诉PC1自己的IP和MAC地址。


二、ARP数据包信息

ARP数据的详细信息列表如下

Hardware type 硬件类型,标识链路层协议
Protocol type 协议类型,标识网络层协议
Hardware size 硬件地址大小,标识MAC地址长度,这里是6个字节(48bit)
Protocol size 协议地址大小,标识IP地址长度,这里是4个字节(32bit)
Opcode 操作代码,标识ARP数据包类型,1表示请求,2表示回应
Sender MAC address 发送者MAC
Sender IP address 发送者IP
Target MAC address 目标MAC,此处全0表示在请求
Target IP address 目标IP

ARP请求包

blob.png

ARP应答包

内容格式和上图相似,不过会有目的地址对应的MAC地址,ARP数据包类型字段为2。


三、ARP攻击

新建 Microsoft Visio 绘图 (3).png

我们知道,当PC1对PC2正常通信的时候(先别管攻击者PC3),PC2、PC1会先后建立对方的IP和MAC地址的映射(即建立ARP缓存表),同时对于交换机而言,它也具有记忆功能,会基于源MAC地址建立一个CAM缓存表(记录MAC对应接口的信息),理解为当PC1发送消息至交换机的Port1时,交换机会把源MAC(也就是MAC1)记录下来,添加一条MAC1和Port1的映射,之后交换机可以根据MAC帧的目的MAC进行端口转发,这个时候PC3只是处于监听状态,会把PC1的广播丢弃。

正常的PC3会把广播包丢弃,同样的PC3可以抓住这一环节的漏洞,把不属于自己的广播包接收,同时回应一个虚假的回应包,告诉PC1我就是PC2

(IP2-MAC3),这样PC1会收到两个回应包(一个正确的IP2-MAC2,一个虚假的IP2-MAC3),但是PC1并不知道到底哪个是真的,所以PC1会做出判断,并且判断后到达的为真,那么怎么让虚假的回应包后到达呢,PC3可以连续不断的发送这样的回应包,总会把哪个正确的回应包覆盖掉。

而后PC1会建立IP2-MAC3这样一条ARP缓存条目,以后当PC1给PC2发送信息的时候,PC1依据OSI模型从上至下在网络层给数据封装目的IP为IP2的包头,在链路层通过查询ARP缓存表封装目的MAC为MAC3的数据帧,送至交换机,根据查询CAM表,发现MAC3对应的接口为Port3,就这样把信息交付到了PC3,完成了一次ARP攻击。

1520303928467978

如果ARP攻击严重话,会导致同一个局域网(也是同一个广播域)的所有主机的ARP缓存表中都存放着错误的IP和MAC的映射,如上图,每台主机的ARP缓存表中,不论哪个IP,都会映射到攻击者的MAC地址MAC1上,这样该局域网内的所有主机的消息都发送到Hacker的主机上。

转自:https://blog.51cto.com/13570193/2083332

Underfitting and Overfitting

[TOC]

1. underfitting and overfitting

我们利用多项式回归获得更加准确的拟合曲线,实现了对训练数据更好的拟合。然而,我们也发现,过渡地对训练数据拟合也会丢失信息规律。看两个概念:

  • 欠拟合(underfitting):拟合程度不高,数据距离拟合曲线较远,如下左图所示。
  • 过拟合(overfitting):过度拟合,貌似拟合几乎每一个数据,但是丢失了信息规律,如下右图所示,房价随着房屋面积的增加反而降低了。

underfitting_and_overfitting

我们有如下策略来解决过拟合问题:

  1. 减少特征数,显然这只是权宜之计,因为特征意味着信息,放弃特征也就等同于丢弃信息,要知道,特征的获取往往也是艰苦卓绝的。
  2. 不放弃特征,而是拉伸曲线使之更加平滑以解决过拟合问题,为了拉伸曲线,也就要弱化一些高阶项(曲线曲折的罪魁祸首)。由于高阶项中的特征 x 无法更改,因此特征是无法弱化的,我们能弱化的只有高阶项中的系数 θi。我们把这种弱化称之为是对参数 θ 的惩罚(penalize)。**Regularization(正规化)**正是完成这样一种惩罚的“侩子手”。

如下例所示,我们将 θ3 及 θ4 减小(惩罚)到趋近于 0,原本过拟合的曲线就变得更加平滑,趋近于一条二次曲线(在本例中,二次曲线显然更能反映住房面积和房价的关系),也就能够更好的根据住房面积来预测房价。要知道,预测才是我们的最终目的,而非拟合。

regularization

2. Regularized Linear Regression

在线性回归中,我们的预测代价如下评估:

$$J(\theta)=\frac{1}{2m}\sum\limits_{i=1}^m(h_\theta(x^{(i)})-y^{(i)})^2$$

为了在最小化 J(θ) 的过程中,也能尽可能使 $θ$ 变小,我们将上式更改为:

$$\begin{align*} J(\theta) &= \frac{1}{2m}\sum\limits_{i=1}^m(h_\theta(x^{(i)})-y^{(i)})^2+\lambda\sum\limits_{i=1}^{n}\theta_j^2 \ &= \frac{1}{2m}(X\theta-y)^T(X\theta-y)+\lambda\sum\limits_{i=1}^{n}\theta_j^2 \end{align*}$$

其中,参数 λ 主要是完成以下两个任务:

  1. 保证对数据的拟合良好
  2. 保证 $θ$ 足够小,避免过拟合问题。

λ 越大,要使 $J(θ)$ 变小,惩罚力度就要变大,这样 θ 会被惩罚得越惨(越小),即要避免过拟合,我们显然应当增大 λλ 的值。

那么,梯度下降也发生相应变化:

$$\begin{align*} \theta_0 &=\theta_0-\alpha\frac{1}{m}\sum\limits_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})x_0^{(i)} \ \theta_j &=\theta_j-\alpha\big(\frac{1}{m}\sum\limits_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})x_j^{(i)}+\frac{\lambda}{m}\theta_j\big) \quad (1) \ \mbox {即:}& \ \theta &= \theta-\alpha*(\frac{1}{m} X^T(y-X\theta) + \frac{\lambda}{m}\theta_{j}) \quad j \neq 0 \end{align*}$$

其中,**(1)**式等价于:

$$\theta_j=\theta_j(1-\alpha\frac{\lambda}{m})-\alpha\frac{1}{m}\sum\limits_{i=1}^{m}[h_\theta(x^{(i)})-y^{(i)}]x_j^{(i)}$$

由于 $1-\alpha\frac{\lambda}{m}\lt1$ ,故而梯度下降中每次更新 θ,同时也会去减小 θ 值,达到了 Regularization 的目的。

如果使用正规方程,则使 J(θ) 最小化的 θ 值为:

$$\theta=(X^TX+\lambda\left[\begin{array}{ccccc}0 &\cdots &\cdots &\cdots &0 \ 0 &1 &\cdots &\cdots &0\ \vdots & \vdots & 1 &\cdots & 0\ \vdots &\vdots &\cdots &\ddots & \vdots \ 0 & 0 &\cdots &\cdots &1 \end{array}\right])^{-1}X^Ty$$

3. Regularized Logistic Regression

逻辑回归中的正规化,代价评估如下:

$$\begin{align*} J(\theta) &=\frac{1}{m}\sum\limits_{i=1}^{m}y^{(i)}logh_0(x^{(i)})+(1-y^{(i)})log(1-h_\theta(x^{(i)}))+\frac{\lambda}{2m}\sum\limits_{j=1}^{n}\theta_j^2 \ &= \frac{1}{m}\big((,log,(g(X\theta))^Ty+(,log,(1-g(X\theta))^T(1-y)\big) + \frac{\lambda}{2m}\sum_{j=1}^{n}\theta_{j}^{2} \end{align*}$$

梯度下降如下:

$$\begin{align*} \theta_0 &=\theta_0-\alpha\frac{1}{m}\sum\limits_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})x_0^{(i)} \ \theta_j &=\theta_j-\alpha\big(\frac{1}{m}\sum\limits_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})x_j^{(i)}+\frac{\lambda}{m}\theta_j\big) \ \mbox {即:}& \ \theta &= \theta - \alpha*(\frac{1}{m} X^T(y-g(X\theta)) + \frac{\lambda}{m}\theta_{j}) \quad j \neq 0 \end{align*}$$

Logistic Regression

[TOC]

1. Classification and Representation

使用线性回归来处理 0/1 分类问题总是困难重重的,如下两图,在第一幅图中,拟合曲线成功的区分了 0、1 两类,在第二幅图中,如果我们新增了一个输入(右上的 X 所示),此时拟合曲线发生变化,由第一幅图中的紫色线旋转到第二幅图的蓝色线,导致本应被视作 1 类的 X 被误分为了 0 类:

线性回归处理分类问题1

线性回归处理分类问题2

因此,人们定义了逻辑回归来完成 0/1 分类问题。

1.1 sigmoid

用线性回归预测函数hθ(x)来处理回归问题不太有效,特别对于0/1分类问题。新的逻辑回归预测函数

回归预测函数

g(z) 称之为 Sigmoid Function,亦称 Logic Function,其函数图像如下:

sigmoid

预测函数hθ(x) 被很好地限制在0、1之间。阈值为 0.5,大于则为 1 类,反之为 0 类。函数曲线过渡光滑自然。

1.2 Decision Boundary

决策边界,顾名思义,就是用来划清界限的边界,边界的形态可以不定,可以是点,可以是线,也可以是平面。Andrew Ng 在公开课中强调:“决策边界是预测函数 hθ(x)hθ(x) 的属性,而不是训练集属性”,这是因为能作出“划清”类间界限的只有 hθ(x),而训练集只是用来训练和调节参数的。

  • 线性决策边界

    线性决策边界

  • 非线性决策边界

    非线性决策边界

2. Logistic Regression Model

2.1 Cost Function

cost_function

当y=0时:

cost_function_y0

当y=1时:

cost_function_y1

可以看到,当 hθ(x)≈y 时,cost≈0,预测正确。

cost_function_y1

2.2 Gradient Descent

首先了解下sigmoid函数的倒数:

partial_derivative_of_sigmoid

由此可以得出使用梯度下降来调节 θ 的公式:

gradient_descent

向量表示

gradient_descent_v

3.Multiclass Classification

通常采用 One-vs-All 方法来实现多分类,其将多分类问题转化为了多次二分类问题。假定完成 K 个分类,One-vs-All 的执行过程如下:

  1. 轮流选中某一类型 i ,将其视为正样本,即 “1” 分类,剩下样本都看做是负样本,即 “0” 分类。
  2. 训练逻辑回归模型得到参数 θ(1),θ(2),…,θ(K)θ(1),θ(2),…,θ(K) ,即总共获得了 K−1 个决策边界。

multiclass_1

给定输入 xx,为确定其分类,需要分别计算 h(k)θ(x),k=1,…,Khθ(k)(x),k=1,…,K,h(k)θ(x)hθ(k)(x) 越趋近于 1,xx 越接近是第 kk类:

multiclass_2

Programming Exercise 1 Linear Regression

[TOC]

1. Introduction

任务所要用到的文件

Files included in this exercise
ex1.m - Octave/MATLAB script that steps you through the exercise
ex1 multi.m - Octave/MATLAB script for the later parts of the exercise
ex1data1.txt - Dataset for linear regression with one variable
ex1data2.txt - Dataset for linear regression with multiple variables
submit.m - Submission script that sends your solutions to our servers
[?] warmUpExercise.m - Simple example function in Octave/MATLAB
[?] plotData.m - Function to display the dataset
[?] computeCost.m - Function to compute the cost of linear regression
[?] gradientDescent.m - Function to run gradient descent
[†] computeCostMulti.m - Cost function for multiple variables
[†] gradientDescentMulti.m - Gradient descent for multiple variables
[†] featureNormalize.m - Function to normalize features
[†] normalEqn.m - Function to compute the normal equations
? indicates files you will need to complete
† indicates optional exercises

2. Assignment

2.1 Simple Octave/MATLAB function

这一步很简单,在写好的函数内添加内容

打开warmUpExercise.m文件

1
2
3
4
5
6
7
8
9
10
function A = warmUpExercise()

% ============= YOUR CODE HERE ==============

% 在这里添加内容
A = eye(5);

% ===========================================

end

2.2 Linear regression with one variable

这一节有三个任务:

  1. 可视化数据
  2. 计算梯度下降
  3. 结果可视化

2.2.1 Plotting the Data

导入'ex1data1.txt 文件数据,然后显示

首先写一个显示数据的函数plotData 保存到文件plotData.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function plotData(x, y)
figure; % open a new figure window

% ====================== YOUR CODE HERE ======================

plot(x, y, 'rx', 'MarkerSize', 10);
% marker
% 'x' cross
% color
% 'r' Red
% 用红色叉叉标记坐标点,标记大小为10
% ============================================================

end

plot使用

导入数据,调用函数plotData

ex1data1.txt:

1
2
3
4
5
6
6.1101,17.592
5.5277,9.1302
8.5186,13.662
7.0032,11.854
5.8598,6.8233
...
1
2
3
data = load('ex1data1.txt');
X = data(:, 1); y = data(:, 2);
plotData(X, y);

结果展示:

ex1data1.png

2.2.2 Gradient Descent

首先计算损失函数,公式如下:

formula_1.png

代码文件computeCost.m

1
2
3
4
5
6
7
8
9
10
11
12
function J = computeCost(X, y, theta)

m = length(y); % number of training examples
J = 0;

% ====================== YOUR CODE HERE ======================

J = sum((X*theta -y).^2)/2/m;

% ============================================================
end

然后计算梯度下降,公式如下:

formula_2.png

代码文件gradientDescent.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)

m = length(y); % number of training examples
J_history = zeros(num_iters, 1);

for iter = 1:num_iters

% ====================== YOUR CODE HERE ======================

theta = theta - (sum(alpha * (X*theta -y).*X)/m)';

% ============================================================

% Save the cost J in every iteration
J_history(iter) = computeCost(X, y, theta);

end

end

最后绘制回归曲线

1
2
3
4
5
theta = gradientDescent(X, y, theta, alpha, iterations);
hold on; % keep previous plot visible
plot(X(:,2), X*theta, '-')
legend('Training data', 'Linear regression')
hold off % don't overlay any more plots on this figure

legend 为每个绘制的数据序列创建一个带有描述性标签的图例。

Linear regression.png

2.2.3 Visualizing J(θ)

损失值可视化,这部分不用自己写代码。首先通过linspace 取一些范围theta值。然后调用computeCost获取每一组theta值的cost。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
% Grid over which we will calculate J
theta0_vals = linspace(-10, 10, 100);
theta1_vals = linspace(-1, 4, 100);

% initialize J_vals to a matrix of 0's
J_vals = zeros(length(theta0_vals), length(theta1_vals));

% Fill out J_vals
for i = 1:length(theta0_vals)
for j = 1:length(theta1_vals)
t = [theta0_vals(i); theta1_vals(j)];
J_vals(i,j) = computeCost(X, y, t);
end
end

获取到cost之后调用surf 函数画出来一个三维曲面图。代码如下:

1
2
3
4
5
6
7
% Because of the way meshgrids work in the surf command, we need to
% transpose J_vals before calling surf, or else the axes will be flipped
J_vals = J_vals';
% Surface plot
figure;
surf(theta0_vals, theta1_vals, J_vals)
xlabel('\theta_0'); ylabel('\theta_1');

cost.png

等高线图

1
2
3
4
5
6
7
8
% Contour plot
figure;
% Plot J_vals as 15 contours spaced logarithmically between 0.01 and 100
contour(theta0_vals, theta1_vals, J_vals, logspace(-2, 3, 20))
xlabel('\theta_0'); ylabel('\theta_1');
hold on;
plot(theta(1), theta(2), 'rx', 'MarkerSize', 10, 'LineWidth', 2);
% theta是通过前面计算出来的最优参数。

等高线.png

2.3 Linear regression with multiple variables

2.3.1 特征归一化(Feature Normalization)

代码文件featureNormalize.m

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function [X_norm, mu, sigma] = featureNormalize(X)

% You need to set these values correctly
X_norm = X;
mu = zeros(1, size(X, 2));
sigma = zeros(1, size(X, 2));

% ====================== YOUR CODE HERE ======================

mu = mean(X);
sigma = std(X);
X_norm = (X - mu)./sigma;

% X_norm = (X - mean(X))./std(X);

% ============================================================

end

2.3.2 Gradient Descent

对于矩阵向量之间的计算多变量和单变量的公式都一样。所以computeCostMulti.m and gradientDescentMulti.m 两个文件代码请看前面。

绘制成本函数曲线:

1
2
3
4
5
6
7
8
9
10
11
12
13
% Choose some alpha value
alpha = 0.03;
num_iters = 400;

% Init Theta and Run Gradient Descent
theta = zeros(3, 1);
[theta, J_history] = gradientDescentMulti(X, y, theta, alpha, num_iters);

% Plot the convergence graph
figure;
plot(1:numel(J_history), J_history, '-b', 'LineWidth', 2);
xlabel('Number of iterations');
ylabel('Cost J');

CostJ.png

2.3.3 Normal Equations

寻找最优参数theta,还可以通过正规方程实现,不用设置学习率α和特征缩放,也不用计算梯度下降,迭代至收敛。公式:

figure6.png

代码文件:normalEqn.m

1
2
3
4
5
6
7
8
9
10
11
function [theta] = normalEqn(X, y)

theta = zeros(size(X, 2), 1);

% ====================== YOUR CODE HERE ======================

theta = pinv(X'*X)*X'*y

% ============================================================

end

至此,作业1完成,Congratulation!

Linear Regression with Multiple Variables (week2)

[TOC]

Multiple Features

多个特征的数据

Multiple_Features_01

对于线性回归:

Multiple_Features_02

其中:X0 = 1

Gradient Descent for Multiple Variables

对于m个样本,n个特征的,

Gradient_Descent_for_Multiple_Variables_02

Gradient_Descent_for_Multiple_Variables_01

Feature Scaling

对训练数据进行特征缩放可以加快训练速度。

有两种帮助的技术是特征缩放均值归一化。特征缩放涉及将输入值除以输入变量的范围(即最大值减去最小值),从而产生仅1的新范围。均值归一化涉及从该值中减去输入变量的平均值。输入变量导致输入变量的新平均值仅为零。要实现这两种技术,请调整输入值,如下面的公式所示:

Multiple_Features_03

Features and Polynomial Regression

特征和多项式回归不一样,We can improve our features and the form of our hypothesis function in a couple different ways.

可以通过组合特征生成新的特征,We can combine multiple features into one. For example, we can combine x_1 and x_2 into a new feature x_3 by taking x_1⋅x_2.

可以通过取平方,立方,平方根等方法增加多项式,We can change the behavior or curve of our hypothesis function by making it a quadratic, cubic or square root function (or any other form).

Normal Equation

正规方程:在通过迭代更新参数theta的时候,当偏导数项为0 的时候,就是参数theta的最终值。所以通过这种方式来求得theta值的方法,就是正规方程。

Normal_Equation_02

下面是例子以及跟梯度下降的对比。

Normal_Equation_01

梯度下降 正规方程
需要选择适当的学习率 α 不要学习率 α
需要进行多步迭代 不需要进行迭代,在 Matlab 等平台上,矩阵运算仅需一行代码就可完成
对多特征适应性较好,能在特征数量很多时仍然工作良好 算法复杂度为 O(n3),所以如果特征维度太高(特别是超过 10000 维),那么不宜再考虑该方法。
能应用到一些更加复杂的算法中,如逻辑回归(Logic Regression)等 矩阵需要可逆,并且,对于一些更复杂的算法,该方法无法工作

注意:

Normal_Equation_03

model and cost function (week1)

[TOC]

1.Model Representation

定义:给定一个训练数据集,学习一个函数作为预测器(假设函数hypothesis),这个预测器就是模型。

given a training set, to learn a function h : X → Y so that h(x) is a “good” predictor for the corresponding value of y. this function h is called a hypothesis.

model_representation_01

2.Cost Function

损失函数 定义:用来衡量假设函数的准确性。

对给定的输入x,用预测值(h(x)和真实值y的函数f(h(x), y) 计算得,不同的数据和模型有不同的函数。如果预测结果和真实值越接近,则说明模型学习的越好。如下例子:

cost_function_01

cost_function_02

cost_function_03

不同的模型参数theta得到不同的模型,对应的损失函数值也不同,通过最小化损失函数来寻找最好的模型。

对于不同的模型,拥有不同的损失函数曲线图,等高线上面的损失值是相等的,虽然模型参数值可能不同。

cost_function_04

cost_function_05

cost_function_06

3.Gradient Descent

梯度下降:每个模型有对应的模型参数,损失函数用来衡量模型与数据之间的匹配程度。为了让模型更加的匹配数据,需要对模型参数进行调整,而梯度下降是一种更新模型参数的方法

gradient_descent_01

注意:在更新参数的时候,计算偏导数 Partial derivative 的时候,使用的是本轮迭代参数更新之前的参数,而不是前面更新了参数,立马在后面的求偏导数中使用更新的参数计算。

gradient_descent_02

对于学习率的选择:

learning_rate_01

learning_rate_02

Gradient Descent For Linear Regression

看公式:

Gradient_Descent_For_Linear_Regression_01

Gradient_Descent_For_Linear_Regression_02

4.Matrix and Vector

Matrix:矩阵是一个二维数组

Vector:只有一列的二维数组

Matrix_and_Vector_01

Inverse and Transpose

Transpose:转置

Matrix_and_Vector_02

Inverse: 逆矩阵

单位矩阵 = 矩阵A × 逆矩阵inv(A)

example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
% Initialize matrix A 
A = [1,2,0;0,5,6;7,0,9]

% Transpose A
A_trans = A'

% Take the inverse of A
A_inv = inv(A)

% What is A^(-1)*A?
A_invA = inv(A)*A

% A =
% 1 2 0
% 0 5 6
% 7 0 9

% A_trans =
% 1 0 7
% 2 5 0
% 0 6 9

% A_inv =
% 0.348837 -0.139535 0.093023
% 0.325581 0.069767 -0.046512
% -0.271318 0.108527 0.038760

% A_invA =
% 1.00000 -0.00000 0.00000
% 0.00000 1.00000 -0.00000
% -0.00000 0.00000 1.00000


octave安装和基本使用

[TOC]

Octabe install

推荐 使用Octave安装包安装.

On Ubuntu, you can use:

1
sudo apt-get update && sudo apt-get install octave

On Fedora, you can use:

1
sudo yum install octave-forge 

Octave 使用

官方文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
GNU Octave, version 4.2.2
Copyright (C) 2018 John W. Eaton and others.
Octave was configured for "x86_64-pc-linux-gnu".
...
For more information, visit http://www.octave.org/get-involved.html

>> 1 ==2
ans = 0
>> 1~=2
ans = 1
# 9x9 随机 0~1
>> rand(9,9)
ans =

0.3560386 0.4607871 0.8059847 0.2042094 0.2411058 0.9311803 0.8023873 0.8208079 0.9631931
0.4604231 0.0222901 0.6693275 0.5887816 0.0076518 0.1670580 0.6335819 0.1711659 0.1405882
0.0519485 0.3400714 0.2909762 0.3687556 0.7300303 0.3436051 0.1679526 0.2550348 0.0342722
0.9379501 0.7760394 0.0859048 0.3292712 0.2385854 0.8567406 0.2433711 0.8027390 0.4103872
0.8297066 0.5138018 0.3540072 0.7688630 0.7550758 0.0676738 0.3528168 0.5365513 0.8800598
0.3350162 0.8376844 0.7863446 0.6448189 0.1355422 0.0235755 0.2975952 0.2879286 0.8854084
0.2484960 0.2086548 0.4821656 0.5838678 0.2676164 0.8016253 0.5552146 0.2787187 0.7647289
0.7559019 0.2639478 0.4199944 0.5312557 0.5202589 0.7852354 0.5681352 0.1088001 0.6572705
0.9477478 0.4998028 0.4179308 0.0513819 0.8775790 0.5860457 0.3993368 0.3765168 0.2140254

>> ones(9,9)
ans =

1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1

>> W = zeros(9,9);
>> W
W =

0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0

>> rand(1, 2)
ans =
0.76409 0.77792

>> sqrt(9)
ans = 3
1
2
3

>> A = rand(1, 100000);
>> hist(A, 20)

octave_04

1
2
3
# 符合正太分布的随机数,randn,  u=0,seigema=1
>> A = randn (1,10000);
>> hist(A, 50)

octave_03

1
2
3
4
# u= -10 , segema = 98
>> W = -10 + sqrt(98)*(randn(1,10000));
>> hist(W)
>> hist(W, 50)

octave_01

octave_02

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

>> eye(5)
ans =

Diagonal Matrix #单位矩阵

1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1

>> size (W)
ans =

1 10000

>> length (W)
ans = 10000
>> W = zeros (5)
W =

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

>> length (W)
ans = 5

>> W = zeros (5, 4)
W =

0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

>> length (W)
ans = 5

>> W = zeros (2, 4)
W =

0 0 0 0
0 0 0 0

>> length (W)
ans = 4

# 注意,length 表示 航和列中,较大的这个
# length (W) = max (size (A))

octave还可以执行部分shell命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

>> pwd
ans = /home/alex/data_files/software/xmind/xmind-8-update8-linux/XMind_amd64
>> cd
>> pwd
ans = /home/alex
>> ls
2018-10-16 18-01-44

>> load sogou-qimpanel:0.pid

>> who
Variables in the current scope:

W ans

举证其他表示方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

>> A = [1 2; 3 4; 5 6]
A =

1 2
3 4
5 6

>> B = [11 12; 13 14; 15 16]
B =

11 12
13 14
15 16

>> C = [A B]
C =

1 2 11 12
3 4 13 14
5 6 15 16

>> D = [A; B]
D =

1 2
3 4
5 6
11 12
13 14
15 16

# transpose
>> D'
ans =

1 3 5 11 13 15
2 4 6 12 14 16

>> E = rand(5)
E =

0.382889 0.826820 0.143657 0.105050 0.799284
0.342433 0.729053 0.571096 0.498017 0.581522
0.299401 0.346902 0.273341 0.138887 0.505162
0.745145 0.132160 0.319004 0.978364 0.488847
0.368702 0.029850 0.391279 0.496332 0.533725

>> E = rand(5,1)
E =

0.99898
0.63184
0.95289
0.37744
0.91223

最大值

1
2
3
4
5
6
7
8
9
10
>> E = rand(1,10)
E =

0.790997 0.471432 0.598649 0.593467 0.342134 0.960598 0.752763 0.021469 0.271880 0.111108

>> max (E)
ans = 0.96060
>> [value, index] = max(E)
value = 0.96060
index = 6

过滤筛选

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

>> E < 0.5
ans =

0 1 0 0 1 0 0 1 1 1

>> find(E < 0.5)
ans =

2 5 8 9 10

>> E
E =

0.790997 0.471432 0.598649 0.593467 0.342134 0.960598 0.752763 0.021469 0.271880 0.111108

>> [value, index] = find(E<0.5)
value =

1 1 1 1 1

index =

2 5 8 9 10

>> E = rand(5,5)
E =

0.787163 0.617232 0.703976 0.436314 0.410497
0.440223 0.812849 0.242780 0.869555 0.278506
0.240996 0.931844 0.060643 0.612793 0.227300
0.451394 0.673056 0.184734 0.143215 0.803382
0.795615 0.979938 0.857430 0.963706 0.765059

>> [value, index] = find(E<0.5)
value =

2
3
4
2
3
4
1
4
1
2
3

index =

1
1
1
3
3
3
4
4
5
5
5

>> [rows, colums] = find(E<0.5)
rows =

2
3
4
2
3
4
1
4
1
2
3

colums =

1
1
1
3
3
3
4
4
5
5
5

相关计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

>> sum(E)
ans =

2.9953 2.4057 2.3705 3.2331 2.2077

>> prod(E)
ans =

0.0337328 0.0098164 0.0058173 0.0925647 0.0138977

>> floor (E)
ans =

0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0

>> ceil (E)
ans =

1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

>> F = randn (5)
F =

1.73542 -0.97333 0.90465 0.28529 1.89615
-0.56606 -0.78233 -1.20289 0.77386 0.64770
-1.54203 0.49252 1.34071 1.56246 -1.48515
-1.82310 -1.68507 1.41672 -1.24164 -0.20081
1.12516 0.63253 -1.90412 -1.23104 0.66748

>> ceil (F)
ans =

2 -0 1 1 2
-0 -0 -1 1 1
-1 1 2 2 -1
-1 -1 2 -1 -0
2 1 -1 -1 1

>> floor (F)
ans =

1 -1 0 0 1
-1 -1 -2 0 0
-2 0 1 1 -2
-2 -2 1 -2 -1
1 0 -2 -2 0

>> prod(F)
ans =

-3.10731 -0.39973 3.93571 0.52725 0.24448

>> sum(F)
ans =

-1.07060 -2.31567 0.55507 0.14892 1.52537

>> G1 = rand(3)
G1 =

0.536005 0.039219 0.756845
0.378762 0.097467 0.124591
0.567407 0.395335 0.371280

>> G2 = rand(3)
G2 =

0.210937 0.263702 0.241626
0.191786 0.871084 0.903337
0.350747 0.768891 0.047243

>> max(G1,G2)
ans =

0.53601 0.26370 0.75684
0.37876 0.87108 0.90334
0.56741 0.76889 0.37128

>> max(G1)
ans =

0.56741 0.39533 0.75684

>> max(G1, [], 1)
ans =

0.56741 0.39533 0.75684

>> max(G1, [], 2)
ans =

0.75684
0.37876
0.56741

>> max(max(G1))
ans = 0.75684
>> max(G1(:))
ans = 0.75684
>> G1(:)
ans =

0.536005
0.378762
0.567407
0.039219
0.097467
0.395335
0.756845
0.124591
0.371280

>> A
A =

1 2
3 4
5 6

magic使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49


>> magic (9)
ans =

47 58 69 80 1 12 23 34 45
57 68 79 9 11 22 33 44 46
67 78 8 10 21 32 43 54 56
77 7 18 20 31 42 53 55 66
6 17 19 30 41 52 63 65 76
16 27 29 40 51 62 64 75 5
26 28 39 50 61 72 74 4 15
36 38 49 60 71 73 3 14 25
37 48 59 70 81 2 13 24 35

>> eye (9)
ans =

Diagonal Matrix

1 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 1

>> magic (9) .* eye (9)
ans =

47 0 0 0 0 0 0 0 0
0 68 0 0 0 0 0 0 0
0 0 8 0 0 0 0 0 0
0 0 0 20 0 0 0 0 0
0 0 0 0 41 0 0 0 0
0 0 0 0 0 62 0 0 0
0 0 0 0 0 0 74 0 0
0 0 0 0 0 0 0 14 0
0 0 0 0 0 0 0 0 35

>> sum(sum(magic (9) .* eye(9)))
ans = 369
>> sum(magic (9) .* eye(9))
ans =

47 68 8 20 41 62 74 14 35

逆矩阵和转置

inverse and transport

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# θ = ( X^T X )^−1 X^T y 
# theta = pinv(X'*X)*X'*y
# inv pinv, pinv 可以处理逆矩阵不是线性相关的问题。
>> A
A =

30 39 48 1 10 19 28
38 47 7 9 18 27 29
46 6 8 17 26 35 37
5 14 16 25 34 36 45
13 15 24 33 42 44 4
21 23 32 41 43 3 12
22 31 40 49 2 11 20

>> pinv(A)
ans =

8.1633e-04 8.1633e-04 2.1165e-02 -1.9533e-02 -2.0907e-03 4.1386e-03 4.0104e-04
-2.0907e-03 2.4072e-02 -1.9533e-02 1.2316e-03 4.0104e-04 8.1633e-04 8.1633e-04
2.1165e-02 -1.9117e-02 4.0104e-04 -2.0907e-03 3.7233e-03 8.1633e-04 8.1633e-04
-1.7041e-02 8.1633e-04 8.1633e-04 8.1633e-04 8.1633e-04 8.1633e-04 1.8673e-02
8.1633e-04 8.1633e-04 -2.0907e-03 3.7233e-03 1.2316e-03 2.0750e-02 -1.9533e-02
8.1633e-04 8.1633e-04 1.2316e-03 4.0104e-04 2.1165e-02 -2.2439e-02 3.7233e-03
1.2316e-03 -2.5059e-03 3.7233e-03 2.1165e-02 -1.9533e-02 8.1633e-04 8.1633e-04

>> A * pinv(A)
ans =

1.0000e+00 -4.5103e-17 -1.5266e-16 -1.0408e-15 -4.4409e-16 5.5338e-16 7.6675e-16
-7.0907e-16 1.0000e+00 4.7878e-16 2.4633e-16 2.4980e-16 4.2067e-17 -7.4853e-16
7.4463e-16 -1.4485e-16 1.0000e+00 -8.9165e-16 2.4980e-16 1.1493e-16 4.3455e-16
-3.3437e-16 5.2822e-16 -4.3715e-16 1.0000e+00 2.7756e-17 1.6697e-16 -6.5052e-17
-1.2317e-16 2.1684e-16 -1.8908e-16 -5.9674e-16 1.0000e+00 2.5847e-16 9.9053e-16
-6.6787e-16 -3.0878e-16 1.0270e-15 6.9389e-17 -2.7756e-17 1.0000e+00 -5.2042e-16
-5.9501e-16 1.0408e-17 4.8572e-16 -1.3878e-17 3.3307e-16 -1.9082e-17 1.0000e+00

画图

1
2
3
4
5
>> t=[0:0.01:0.98];
>> y1=sin(2*pi*4*t);
>> plot(t,y1);
>> y2=cos(2*pi*4*t);
>> plot(t,y2)

octave_05

octave_06

一个图,多个曲线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>> t=[0:0.01:0.98];
>> y1=sin(2*pi*4*t);
>> y2=cos(2*pi*4*t);
>> hold on; #保持上图
>> plot(t,y1);
>> plot(t,y2)
>> xlabel ('time')
>> ylabel ('value')
# 图例线
>> legend('sin', 'cos')
>> title('my plot')
# 导出
>> cd
>> print -dpng 'myplot.png'

octave_07

多个figure同时呈现

1
2
3
4
5
6
>> t=[0:0.01:0.98];
>> y1=sin(2*pi*4*t);
>> y2=cos(2*pi*4*t);
>> hold on;
>> figure (1);plot(t,y1);
>> figure (2);plot(t,y2);

octave_09

子图显示

1
2
3
4
>> subplot (1,2,1);
>> plot(t,y1);
>> subplot (1,2,2);
>> plot(t,y2);

octave_08

imagesc

1
2
3
4
5
6
7
8
9
10
11
12
13
>> imagesc (magic (5))
>> imagesc (magic (15)), colorbar, colormap gray;
>> help imagesc
'imagesc' is a function from the file /usr/share/octave/4.2.2/m/image/imagesc.m

-- imagesc (IMG)
-- imagesc (X, Y, IMG)
-- imagesc (..., CLIMITS)
-- imagesc (..., "PROP", VAL, ...)
-- imagesc ("PROP1", VAL1, ...)
-- imagesc (HAX, ...)
-- H = imagesc (...)
Display a scaled version of the matrix IMG as a color image.

octave_10

octave_11

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

>> for i=1:10, v(i)=2^i; end;
>> v
v =

2 4 8 16 32 64 128 256 512 1024

>> include=1:10;
>> for i=include , disp(i); end;
1
2
3
4
5
6
7
8
9
10
>> i=1; while i<=5. v(i) = 100; i=i+1; end
>> v
v =

100 100 100 100 100 64 128 256 512 1024


>> while true,
v(i) = 999;
if i ==7, break;
end; end;
>> v
v =

100 100 100 100 100 999 999 256 512 1024

>> i = 1;
>> while true,
v(i) = 999;
i = i+ 1;
if i ==7, break;
end; end;
>> v
v =

999 999 999 999 999 999 999 256 512 1024

>> x = 2; if x ==1 , disp('the value is one');
elseif x == 2, disp('the value is two');
else disp('the value is not one or two');
end;

好啦,有这些基础就够用啦。再加上有help的帮助,遇到上面问题就知道怎么找解决办法了。

nvidia jetson TX2 刷机

[TOC]

TX2 出厂时,已经自带了 Ubuntu 16.04 系统,可以直接启动。但一般我们会选择刷机,目的是更新到最新的 JetPack L4T,并自动安装最新的驱动、CUDA Toolkit、cuDNN、TensorRT。

刷机注意以下几点:

  • 开发板刷机过程全程联网
  • 除了Jetson TX2之外,您还需要另一台带有Intel或AMD x86处理器的台式机或笔记本电脑。(所以自己要是win电脑,要安装VMware 虚拟机,并在虚拟机上安装Ubuntu 的操作系统,我安装的是Ubuntu -16.04.3 64 位)
  • 这些类型的机器通常被称为PC的个人电脑。该计算机被称为烧录过程的主机。
  • JetPack是一个x86二进制文件,不能在基于ARM的机器上运行

先推荐一个国外刷机技术视频:https://v.qq.com/x/page/b0515967lbr.html
这个视频挺好,虽然是JetPack 3.0刷机,但步骤一模一样。跟着他的步骤刷机就可以,不过有些地方可能不够详细,可以自己先看一遍,有个大致印象。

1. 从官网下载JetPack3.1

下载地址为jetpack, 理论上此处下载需要NVIDIA的帐号。

安装JetPack3.1

  • 现在把刚下载的软件包上传的虚拟机中Ubuntu主机中,可以通过共享文件夹的形式,将JetPack3.1从win电脑copy到vmware虚拟机中的ununtu,这个方法大家可以网上搜下,这里不做赘述。
  • 然后在虚拟机上,终端定位到Jetpack3.1所在文件夹
    更改执行权限:
    $ chmod +x ./JetPack-L4T-3.1-linux-x64.run
    执行安装
    $ sudo ./JetPack-L4T-3.1-linux-x64.run

然后进入了软件界面,

img

jetpack_1_begin_002

  • 选择板子

    jetpack_1_begin_003

  • 随后进入了component manager界面,如图所示:

jetpack_1_begin_004

jetpack_1_begin_005

  • 成功后,就要下载各种包了

jetpack_1_begin_006

jetpack_1_begin_007

jetpack_1_begin_008

连接方式

jetpack_1_begin_009

jetpack_1_begin_010

jetpack_1_begin_011

jetpack_1_begin_012

jetpack_1_begin_013

jetpack_1_begin_014

Prometheus简介

[TOC]

1、Prometheus介绍和架构

1.1 Prometheus介绍

Prometheus是一个开源的系统监视和警报工具包,自2012成立以来,许多公司和组织采用了Prometheus。它现在是一个独立的开源项目,并独立于任何公司维护。在2016年,Prometheus加入云计算基金会作为Kubernetes之后的第二托管项目。

1.1.1 Prometheus的关键特性

  • 由度量名和键值对标识的时间序列数据的多维数据模型
  • 灵活的查询语言
  • 不依赖于分布式存储;单服务器节点是自治的
  • 通过HTTP上的拉模型实现时间序列收集
  • 通过中间网关支持推送时间序列
  • 通过服务发现或静态配置发现目标
  • 图形和仪表板支持的多种模式

1.1.2 Prometheus的组件:

  • 如上图,Prometheus主要由以下部分组成:

    • Prometheus Server:用于抓取和存储时间序列化数据
    • Exporters:主动拉取数据的插件
    • Pushgateway:被动拉取数据的插件
    • Altermanager:告警发送模块
    • Prometheus web UI:界面化,也包含结合Grafana进行数据展示或告警发送

    prometheus本身是一个以进程方式启动,之后以多进程和多线程实现监控数据收集、计算、查询、更新、存储的这样一个C/S模型运行模式。

1.1.3 Prometheus的整体架构

Prometheus从jobs获取度量数据,也直接或通过推送网关获取临时jobs的度量数据。它在本地存储所有被获取的样本,并在这些数据运行规则,对现有数据进行聚合和记录新的时间序列,或生成警报。通过Grafana或其他API消费者,可以可视化的查看收集到的数据。下图显示了Pometheus的整体架构和生态组件:

architecture

Prometheus的整体工作流程:

1)Prometheus 服务器定期从配置好的 jobs 或者 exporters 中获取度量数据;通过推送网关获取临时jobs的度量数据. -Retrieval 负责获取

2)Prometheus 服务器在本地存储收集到的度量数据,并对这些数据进行聚合;- 由TSDB负责存储

3)运行已定义好的 alert.rules,记录新的时间序列或者向告警管理器推送警报。

4)告警管理器根据配置文件,对接收到的警报进行处理,并通过email等途径发出告警。

5)Grafana等图形工具获取到监控数据,并以图形化的方式进行展示。

1.2 Prometheus关键概念

1.2.1 数据模型

Prometheus从根本上将所有数据存储为时间序列:属于相同度量标准和同一组标注尺寸的时间戳值流。除了存储的时间序列之外,普罗米修斯可能会生成临时派生时间序列作为查询的结果。

  • 度量名称和标签:每个时间序列都是由度量标准名称和一组键值对(也称为标签)组成唯一标识。

    • 度量名称指定被测量的系统的特征(例如:http_requests_total-接收到的HTTP请求的总数)。它可以包含ASCII字母和数字,以及下划线和冒号。它必须匹配正则表达式[a-zA-Z_:][a-zA-Z0-9_:]。
    • 标签启用Prometheus的维度数据模型:对于相同度量标准名称,任何给定的标签组合都标识该度量标准的特定维度实例。查询语言允许基于这些维度进行筛选和聚合。更改任何标签值(包括添加或删除标签)都会创建新的时间序列。标签名称可能包含ASCII字母,数字以及下划线。他们必须匹配正则表达式[a-zA-Z_][a-zA-Z0-9_]*。以__开始的标签名称保留给供内部使用。
  • 样本:实际的时间序列,每个序列包括:一个 float64 的值和一个毫秒级的时间戳。

  • **格式:**给定度量标准名称和一组标签,时间序列通常使用以下格式来标识:

    1
    <metric name>{<label name>=<label value>, ...}

    例如,时间序列的度量名称为api_http_requests_total,标签method=”POST”和handler=”/messages”,则标记为:

    1
    api_http_requests_total{method="POST", handler="/messages"}

如下,是在进行数据收集后,在Prometheus中的data目录的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# tree 
.
├── 01EHSWYREVQ296VKWT5MAJEX90
│   ├── chunks
│   │   └── 000001
│   ├── index
│   ├── meta.json
│   └── tombstones
├── 01EHTAP73QPZY1VH6C2K9GHG6H
│   ├── chunks
│   │   └── 000001
│   ├── index
│   ├── meta.json
│   └── tombstones
...
├── chunks_head
│   ├── 000009
│   └── 000010
├── index.html
├── lock
├── queries.active
└── wal
├── 00000006
├── 00000007
├── 00000008
├── 00000009
└── checkpoint.00000005
└── 00000000

prometheus采用time-series(时间序列)方式,存储在本地硬盘

  • prometheus本地T-S数据库以每2小时间隔来分block(块)存储,每个块又分为多个chunk文件,chunk文件用来存放采集的数据的T-S(time-series)数据,metadata和索引文件;
  • index文件是对metrics和labels进行索引之后存储在chunk中,chunk是作为基本存储单位,index和metadata作为子集;
  • prometheus平时采集到的数据先存放在内存之中,对内存消耗大,以缓存的方式可以加快搜索和访问;
  • 在prometheus宕机时,prometheus有一种保护机制WAL,可以将数据定期存入硬盘中以chunk来表示,在重新启动时,可以恢复进内存当中。
  • 当通过API删除序列时,删除的记录存储在单独的tombstone文件中(而不是立即从块文件中删除数据)。

1.2.2 度量类型

Prometheus 客户端库主要提供Counter、Gauge、Histogram和Summery四种主要的 metric 类型:

  • Counter(计算器):Counter是一种累加的度量,它的值只能增加或在重新启动时重置为零。例如,您可以使用计数器来表示提供的请求数,已完成的任务或错误的数量。不要使用计数器来表达可减少的值。例如,不要使用Counter来计算当前正在运行的进程的数量,而是使用Gauge。

  • **Gauge(测量):**Gauge表示单个数值,表达可以任意地上升和下降的度量。Gauge通常用于测量值,例如温度或当前的内存使用情况,但也可以表达上升和下降的“计数”,如正在运行的goroutines的数量。

  • **Histogram(直方图):**Histogram样本观测(例如:请求持续时间或响应大小),并将它们计入配置的桶中。它也提供所有观测值的总和。具有基本度量标准名称的histogram的在获取数据期间会显示多个时间序列:

    • 观察桶的累计计数器,暴露为 _bucket{le=””}
    • 所有观察值的总和,暴露为_sum
    • 已观察到的事件的计数,暴露为_count(等同于_bucket{le=”+Inf”})

    Summery:类似于Histogram,Summery样本观察(通常是请求持续时间和响应大小)。虽然它也提供观测总数和所有观测值的总和,但它计算滑动时间窗内的可配置分位数。在获取数据期间,具有基本度量标准名称的Summery会显示多个时间序列:

    • 流动φ分位数(0≤φ≤1)的观察事件,暴露为{quantile=”<φ>”}
    • 所有观察值的总和,暴露为_sum
    • 已经观察到的事件的计数,暴露为_count

1.2.3 工作和实例

按照Prometheus的说法,可以获取数据的端点被称为实例(instance),通常对应于一个单一的进程。具有相同目的的实例集合(例如为了可伸缩性或可靠性而复制的进程)称为作业(job)

例如,具有四个复制实例的API服务器作业:

  • 工作: api-server
    • 实例1: 1.2.3.4:5670
    • 实例2: 1.2.3.4:5671
    • 实例3: 5.6.7.8:5670
    • 实例4: 5.6.7.8:5671

自动生成标签和时间序列

当Prometheus获取目标时,它会自动附加一些标签到所获取的时间序列中,以识别获取目标:

  • job:目标所属的配置作业名称。
  • instance::被抓取的目标网址部分。

如果这些标签中的任何一个已经存在于抓取的数据中,则行为取决于honor_labels配置选项。

对于每个实例抓取,Prometheus会在以下时间序列中存储一个样本:

  • up{job=””, instance=””}:1 如果实例健康,即可达;或者0抓取失败。
  • scrape_duration_seconds{job=””, instance=””}:抓取的持续时间。
  • scrape_samples_post_metric_relabeling{job=””, instance=””}:应用度量标准重新标记后剩余的样本数。
  • scrape_samples_scraped{job=””, instance=””}:目标暴露的样本数量。

up时间序列是实例可用性的监控。

1.3 在Kubernetes中使用Helm安装Kubernetes

1.3.1 环境要求

  • 已有Kubernetes 1.6+环境;
  • 已部署helm客户端和tiller服务端
  • 在Kubernetes中提供2个容量大于10g的持久化存储卷 (简单示例可以不用部署, 但在生产环境中需要有持久化存储卷)。

1.3.2 通过Chart安装Prometheus

通过执行如下的命令,在Kubernetes中部署Prometheus:

1
$ helm install stable/prometheus --name=prometheus --namespace=kube-system

通过上述命令,将以默认的配置在Kubernetes中部署Prometheus。

1.3.3 Helm3 通过Chart安装Prometheus

使用默认的配置安装, 无需持久化存储卷.(禁止在生产中使用)

1
2
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/prometheus --generate-name

持久化存储卷配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
root@k8s-1:~/helm# helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
root@k8s-1:~/helm# helm fetch prometheus-community/prometheus --version 11.13.1 && tar xf prometheus-11.13.1.tgz

# 修改配置文件内容: server --> persistentVolume --> enabled: true
# prometheus 会自动创建pvc (需要提前创建pv)
root@k8s-1:~/helm# vim prometheus/values.yaml
server:
persistentVolume:
## If true, Prometheus server will create/use a Persistent Volume Claim
## If false, use emptyDir
enabled: true

# 安装prometheus
root@k8s-1:~/helm# helm install prometheus prometheus-community/prometheus --version 11.13.1 -f prometheus/values.yaml

# 查看结果
root@k8s-1:~/helm# kubectl get svc
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# grafana ClusterIP 10.97.71.48 <none> 80/TCP 19h
# kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 5d19h
# kubernetes-dashboard ClusterIP 10.100.12.28 <none> 80/TCP 20h
# nginx-ingress-nginx-ingress NodePort 10.104.8.250 <none> 80:30080/TCP,443:30443/TCP 20h
# prometheus-kube-state-metrics ClusterIP 10.105.185.31 <none> 8080/TCP 19h
# prometheus-node-exporter ClusterIP None <none> 9100/TCP 19h
# prometheus-pushgateway ClusterIP 10.99.225.236 <none> 9091/TCP 19h
# prometheus-server ClusterIP 10.102.32.48 <none> 80/TCP 19h

# 查看存储卷绑定
root@k8s-1:~/helm# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
grafana Bound pv-nfs-v1 10Gi RWO,ROX,RWX 15h
prometheus-alertmanager Bound pv-nfs-v3 10Gi RWO,ROX,RWX 19h
prometheus-server Bound pv-nfs-v2 10Gi RWO,ROX,RWX 18h

1.3.4 页面访问

端口转发: 将服务端口暴露出来. 方便部署验证效果

1
2
3
root@k8s-1:~/helm# export POD_NAME=$(kubectl get pods --namespace default -l "app=prometheus,component=server" -o jsonpath="{.items[0].metadata.name}")
root@k8s-1:~/helm# kubectl --namespace default port-forward --address 0.0.0.0 $POD_NAME 9090
Forwarding from 0.0.0.0:9090 -> 9090

浏览器访问http://IP:Port 即可, 如下图:

prom

Ingress开放服务: 如果kubernetes中部署了Ingress,可以添加Ingress 服务来对外开放端口.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@k8s-1:~/helm# cat demo/ingress-prometheus.yaml 
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-dashboard
namespace: default
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
backend:
serviceName: prometheus-server
servicePort: 80
rules:
- host: prometheus.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
serviceName: prometheus-server
servicePort: 80

访问 prometheus.example.com 效果如上面一样.

horovod

[TOC]

官方介绍

Horovod is a distributed training framework for TensorFlow, Keras, and PyTorch. The goal of Horovod is to make distributed Deep Learning fast and easy to use.

官方测试效果

training

Running Horovod

The example commands below show how to run distributed training. See the Running Horovod page for more instructions, including RoCE/InfiniBand tweaks and tips for dealing with hangs.

1. 单机4卡:

1
2
3
4
5
6
7
# docker
nvidia-docker run -it 172.16.10.10:5000/horovod:0.12.1-tf1.8.0-py3.5
mpirun -np 4 -H localhost:4 python keras_mnist_advanced.py

# singularity
singularity shell --nv /scratch/containers/ubuntu.simg
mpirun -np 4 -H localhost:4 python keras_mnist_advanced.py

2. 多机多卡:

1
2
3
4
$ mpirun -np 16 \
-H server1:4,server2:4,server3:4,server4:4 \
...
python train.py

3. 完整 Docker 使用horovod

4. horovod 完整使用GPU

1. Install NCCL 2.

NCCL 理解

1
2
3
4
# software requirements:
glibc 2.19 or higher
CUDA 8.0 or higher
CUDA devices with a compute capability of 3.0 and higher.

ubuntu install nccl 2

1
2
3
dpkg -i nccl-repo-ubuntu1604-2.1.15-ga-cuda9.1_1-1_amd64.deb #需要登录nvidia申请下载
apt update
apt install libnccl2 libnccl-dev

2. Install Open MPI or another MPI implementation.

1
2
3
4
5
6
7
8
install openmpi
tar xf openmpi-3.1.1.tar.bz2
cd openmpi-3.1.1/
./configure --with-cuda
make -j 12
make install
apt install libopenmpi1.10
mpirun --version

3. Install the horovod pip package.

1
2
3
$ HOROVOD_GPU_ALLREDUCE=NCCL pip install --no-cache-dir horovod #ubuntu have installed nccl2
$ HOROVOD_GPU_ALLREDUCE=MPI pip install --no-cache-dir horovod # use mpi instead nccl2 in allreduce
$ HOROVOD_GPU_ALLREDUCE=MPI HOROVOD_GPU_ALLGATHER=MPI HOROVOD_GPU_BROADCAST=MPI pip install --no-cache-dir horovod # use mpi instead nccl2