BurningBright

  • Home

  • Tags

  • Categories

  • Archives

  • Search

Hello jenkins

Posted on 2019-08-23 | Edited on 2019-10-15 | In tool

install jenkins

Download jenkins.war, tomcat 8
if install suggested plugins report error like this
“No such plugin: cloudbees-folder”

install cloudbees-folder.hpi first

install plugins

install Maven Integration, if error then in plugin management
upload plugin package manually.

proxy server

if jenkins server can’t visit internet then use proxy, and have a try again.
https://github.com/adamfisk/LittleProxy
username:user1
password:user2

maven setting

maven can set proxy too, modify setting.xml, add proxy setting

1
2
3
4
5
6
7
8
9
10
11
<proxy>
<id>optional</id>
<active>true</active>
<protocol>http</protocol>
<username>user1</username>
<password>user2</password>
<host>192.168.1.2</host>
<port>8080</port>
<nonProxyHosts>localhost|127.0.0.1</nonProxyHosts>
</proxy>
</proxies>

git setting

save git account in linux server
vim .git-credentials
add http(s)://{username}:{password}@serverAddress
add setting
git config --global credential.helper store

prevent preocess be killed

  1. add command BUILD_ID=DONTKILLME in every shell input
  2. add param -Dhudson.util.ProcessTree.disable=true in java command
  3. add setting JAVA_OPTS="$JAVA_OPTS -Dhudson.util.ProcessTree.disable=true" in catalina.sh

install jenkins

https://blog.csdn.net/utopiaofartoria/article/details/79612754
https://blog.csdn.net/ming19951224/article/details/80958761

jenkins experience

https://www.jianshu.com/p/06d2c7fda227

setting of tools

https://www.cnblogs.com/wkrbky/p/6351243.html
https://www.cnblogs.com/zhuiluoyu/p/7723949.html

global proxy

https://www.cnblogs.com/EasonJim/p/9826681.html

resources

http://ftp.icm.edu.pl/packages/jenkins/plugins
https://mirrors.tuna.tsinghua.edu.cn/jenkins/plugins/

mysql 5.7 json type

Posted on 2019-08-12 | Edited on 2019-10-15 | In db

none structure data in mysql

in mysql 5.7 , support store data in json type.

create table with virtual column.

1
2
3
4
5
6
CREATE TABLE players (  
id INT UNSIGNED NOT NULL primary key auto_increment,
player JSON NOT NULL,
-- name virtual column
vname VARCHAR(50) GENERATED ALWAYS AS (`player` ->> '$.name') NOT NULL
);
1
SHOW COLUMNS FROM `players`;

prepare save progress

1
2
3
4
-- check whether store procedure open
show variables like 'log_bin_trust_function_creators';
-- open store procedure in mysql
set global log_bin_trust_function_creators=1;
1
2
3
4
5
6
7
8
9
10
11
12
13
delimiter $$
create procedure insert_player(in max_num int(10))
begin
declare i int default 0;
declare json_data varchar(2000) default '1';
set autocommit= 0;
repeat
set i=i+1;
set json_data = concat(concat('{"name":"xxx-',i),'","age":34}');
insert into players (id,player) values(null,json_data);
until i=max_num end repeat;
commit;
end $$

test data, and try

1
call insert_player(2000000);
1
EXPLAIN SELECT * FROM `players` WHERE `vname` = "xxx-990099"
1
CREATE INDEX `name_idx` ON `players`(`vname`);
1
EXPLAIN SELECT * FROM `players` WHERE `vname` = "xxx-990099"

https://blog.csdn.net/bugs4j/article/details/79932538

Hello rabbit

Posted on 2019-08-10 | In db

Install rabbitmq in ubuntu 16.04.1

prepare Ubuntu Server 16.04.1 LTS 64 first

apt-get install rabbitmq-server

check service status
systemctl status rabbitmq-server

daily command

1
2
3
service rabbitmq-server start
service rabbitmq-server stop
service rabbitmq-server restart

manage interface

enable management interface
rabbitmq-plugins enable rabbitmq_management

127.0.0.1:15672 is the default address, guest/guest is the default account.

out account

add user
rabbitmqctl add_user root yourpassword
add role
rabbitmqctl set_user_tags root administrator
add permission

1
2
rabbitmqctl  set_permissions  -p  VHostPath  User  ConfP  WriteP  ReadP
rabbitmqctl set_permissions -p "/" root ".*" ".*" ".*"

enjoy route :)

exchange bind queue route by key in same arguments

https://blog.csdn.net/qq_22638399/article/details/81704372
https://www.cnblogs.com/feixiablog/articles/8317605.html

spring cloud feign support file upload

Posted on 2019-07-30 | Edited on 2019-08-10 | In java

phenomenon

Spring Cloud Feign component not support file upload between micron service.
it may throw exception like this:

1
2
3
4
feign.codec.EncodeException: class [Lorg.springframework.web.multipart.MultipartFile; is not a type supported by this encoder.
at feign.codec.Encoder$Default.encode(Encoder.java:90) ~[feign-core-9.5.1.jar:na]
at feign.form.FormEncoder.encode(FormEncoder.java:87) ~[feign-form-3.3.0.jar:3.3.0]
at feign.form.spring.SpringFormEncoder.encode(SpringFormEncoder.java:64) ~[feign-form-spring-3.3.0.jar:3.3.0]

add dependencies

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>

https://mvnrepository.com/artifact/io.github.openfeign.form/feign-form-spring

be careful the feign-form-spring depend on spring-web it may have conflict with your project.
for example in spring-boot:2.0.5.RELEASE spring-cloud:Finchley.SR1 project has already import
spring-web:5.0.9.RELEASE, if import feign-form-spring:3.3.0 it will import spring-web:4.3.18.RELEASE too,
it cause spring bean creation exception.

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form-spring</artifactId>
<version>3.3.0</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
</exclusions>
</dependency>

file receive part

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@ApiOperation("file upload receive part")
@RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public List<XXX> uploadFile(
@RequestPart(value = "files")
MultipartFile[] files,
@RequestParam(name = "userId")
@ApiParam(name = "userId", value = "用户ID", required = true)
@NotNull(message = "用户ID不能为空")
Long userId,
@RequestParam(name = "userName")
@ApiParam(name = "userName", value = "用户名称", required = true)
@NotBlank(message = "用户名不能为空")
String userName){
...
}

be careful consumes property must add to the annotation RequestMapping
method property must be POST, RequestPart is working.

feign client part

client part is a little complex.

add configuration class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Configuration
public class MultipartSupportConfig {

@Autowired
private ObjectFactory<HttpMessageConverters> messageConverters;

@Bean
@Primary
@Scope("prototype")
public Encoder feignEncoder() {
// return new SpringFormEncoder();
// return new SpringFormEncoder(new SpringEncoder(messageConverters));
return new FeignSpringFormEncoder(new SpringEncoder(messageConverters));
}

@Bean
public feign.Logger.Level multipartLoggerLevel() {
return feign.Logger.Level.FULL;
}

}
  • SpringFormEncoder support single file upload.
  • FeignSpringFormEncoder support file array upload.
  • SpringEncoder avoid project make RequestBody encoding error.

add form encoder

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
public class FeignSpringFormEncoder extends FormEncoder {
/**
* Constructor with the default Feign's encoder as a delegate.
*/
public FeignSpringFormEncoder() {
this(new Default());
}

/**
* Constructor with specified delegate encoder.
*
* @param delegate delegate encoder, if this encoder couldn't encode object.
*/
public FeignSpringFormEncoder(Encoder delegate) {
super(delegate);
MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor(ContentType.MULTIPART);
processor.addWriter(new SpringSingleMultipartFileWriter());
processor.addWriter(new SpringManyMultipartFilesWriter());
}

@Override
public void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException {
if (bodyType.equals(MultipartFile.class)) {
MultipartFile file = (MultipartFile) object;
Map data = Collections.singletonMap(file.getName(), object);
super.encode(data, MAP_STRING_WILDCARD, template);
return;
} else if (bodyType.equals(MultipartFile[].class)) {
MultipartFile[] file = (MultipartFile[]) object;
if(file != null) {
Map data = Collections.singletonMap(file.length == 0 ? "" : file[0].getName(), object);
super.encode(data, MAP_STRING_WILDCARD, template);
return;
}
}
super.encode(object, bodyType, template);
}
}

add interface:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@FeignClient(name = "upload-example", configuration = MultipartSupportConfig.class)
public interface CloudUploadService {

@ApiOperation("文件上传")
@RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
List<XXX> uploadFile(
@RequestPart(value = "files")
MultipartFile[] files,
@RequestParam(name = "userId")
@ApiParam(name = "userId", value = "用户ID", required = true)
@NotNull(message = "用户ID不能为空")
Long userId,
@RequestParam(name = "userName")
@ApiParam(name = "userName", value = "用户名称", required = true)
@NotBlank(message = "用户名不能为空")
String userName);

}

in annotation FeignClient add configuration property, point to the encoding support class.

Testing

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
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class UploadTester {

@Autowired
private CloudUploadService uploadService;

@Test
@SneakyThrows
public void testHandleFileUpload() {

File file = new File("upload.txt");
DiskFileItem fileItem = (DiskFileItem) new DiskFileItemFactory().createItem("file",
MediaType.TEXT_PLAIN_VALUE, true, file.getName());

try (InputStream input = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()) {
IOUtils.copy(input, os);
} catch (Exception e) {
throw new IllegalArgumentException("Invalid file: " + e, e);
}

MultipartFile multi = new CommonsMultipartFile(fileItem);

log.info(uploadService.handleFileUpload(new MultipartFile[]{multi}, 1L, "tester"));
}

}

https://github.com/OpenFeign/feign-form
https://www.jianshu.com/p/4f4d9d084b1d
http://blog.didispace.com/spring-cloud-starter-dalston-2-4/
https://blog.csdn.net/gududedabai/article/details/79895893

maintain log files by shell

Posted on 2019-07-05 | Edited on 2019-07-07 | In linux

move log file to another device

scheduled move specific file to target directory

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/sh
# move log 1 month ago

# get date string
date=`date -d '1 month ago' +'%Y-%m-%d'`

# file name
default="/logs/common-default.log."${date}".log"

if [ -f "$default" ]; then
echo $date' move '$default' to /data0/backup' >> /logs/backup.log
`mv $default /data0/backup`
fi

crontab -e add schedule

1
10 0 * * * sh /move.sh

delete log file by function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/sh
# delete log 1 month ago

# get date string
date=`date -d '1 month ago' +'%Y-%m-%d'`

# find files modify 1 month ago
files=find /data0/backup -type f -not -newermt $date

function delete_log_files
{
while test $# -gt 0
do
`rm -f $1`
echo '$date clean $1' >> /logs/cleanup.log
shift
done
}

delete_log_files $files

delete log file by command

1
2
#!/bin/sh
find /logs/ -type f -mtime +30 -name '*.log' -exec rm -rf {} \;

{} is placeholder of the file be found
\; mean exec command finish


process every line in a multi-line variable
https://cloud.tencent.com/developer/ask/46222

‘crontab’ schedule
https://www.cnblogs.com/peida/archive/2013/01/08/2850483.html

‘find’ command -exec
https://blog.csdn.net/u010900754/article/details/83020378

‘find’ command useage
https://blog.csdn.net/h106140873/article/details/72874455

线性回归和逻辑回归

Posted on 2019-06-30 | Edited on 2019-07-07 | In ml

AndrewNg-Headshot

AndrewNg

就我理解所谓的回归问题,就是做假设,完善这个假设,验证这个假设的过程。
有的假设本身很离谱,完善了也没有好的验证结果;有的问题本身很复杂,假设很难归纳问题。

像西瓜书上说了:No Free Launch Theorem
要根据特定的问题,应用特定的算法,看算法本身的归纳偏好和问题是否匹配。

线性回归

代价函数

其中 $h_{\theta}$ 是假设函数 $\theta^T X$

也就是求目标函数方差最小的参数

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

梯度下降法

每一个参数就是一个维度,求各个维度上的函数变化率,组成向量即梯度。

每一次迭代都向梯度方向前进一小步,其中 alpha 是学习率,最终达到收敛目的

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

正规方程法

即解线性代数的解。

线性方程组的个数不够(样本不够),或参数可相互线性表示(维度耦合度过高)
会导致参数矩阵是一个奇异矩阵,非方正,不可逆;矩阵的秩小于维数,方程组没有唯一解。

向量化

为简化代码,加速计算,需要将计算向量化
在线性回归计算中,将偏导项、损失函数计算向量化:
将假设函数的变量参数当作向量 $\theta$,各个样本作为矩阵行,样本属性作为矩阵列,再在左侧并上偏移向量1。
那么梯度可用 表示,其中 代表当前参数下的样本【误差向量】。
特征向量转置 * 误差向量 / m 得到的标量即,函数在 $ \theta_j $ 维度上的偏导数。
求得所有特征维度上的偏导数组成向量即梯度。

逻辑回归

逻辑回归是使用线性回归的思想,来处理分类问题。
使用sigmoid函数,让原线性方程约束到(0, 1)之间;原有的凸函数也变得非凸,二阶导不一定保持符号。

为了保证损失函数的凸性,需要对原损失函数做一次变换(极大似然法)

1
J = -sum( y' * log(sigmoid(X * theta)) + (1 - y)' * log(1 - sigmoid(X * theta)) ) / m;

梯度方程也发生变化

1
grad = X' * (sigmoid(X * theta) - y) ./ m;

在“回归”时,数值 >= 0.5 为正类, < 0.5 为负类

正则化

算法的泛化能力非常重要,训练过度很可能过拟合,无法在验证集里获得好的效果。
正则化在线性回归中,相当于是在每步迭代中提前缩小了 $\theta$ (实际没变)
这样获得的参数向量不会在谷底,和训练集的拟合度能得到控制,泛化能力得到保障。

梯度下降的正规化

1
J = -sum( y' * log(sigmoid(X * theta)) + (1 - y)' * log(1 - sigmoid(X * theta)) ) / m + (lambda/(2*m)) * sum(theta.^2);

正则化后的梯度为:

1
grad = X' * (sigmoid(X * theta) - y) ./ m + (lambda / m) * theta;

正规方程的正规化

内部加上一个 $\lambda$ 倍的第一行全零的单位矩阵即可。这样还能消除参数矩阵的不可逆问题。


https://www.coursera.org/learn/machine-learning
https://study.163.com/course/courseMain.htm?courseId=1004570029

欧拉-拉格朗日方程练习

Posted on 2019-06-08 | In math

两点之间直线最短

写出AB两点间距离的变分表达:

写表达式的E-L方程:

化简后可得:

可以得知解函数的导数是一个常数 $f’= C_2$
即AB间最短的距离是一条直线

求使旋转双曲面面积最小的函数

写出用盘圆法积分出面积的变分表达式:

写表达式的E-L方程:

化简后可得:

继续化简可得:

根据 $f’= \frac{1}{\sqrt{1-x^2}}$ 可得 $f = arc\cos(x)$
根据 $f’= \frac{1}{\sqrt{x^2-1}}$ 可得 $f = arc\cosh(x)$
重新规划 $x = x/a$ 可得 $f = a arc\cosh(\frac{x}{a}) + b$

线段能围出最大面积的形状是圆

需要用到泛函的拉格朗日乘子法:
有表达式$A_{min} = \int L(f, f’, x)dx$
在约束$B = \int G(f, f’, x)dx = Constant$下
构造 $C = (A - \lambda B)$ 求极值解

写出线段围出面积的变分表达式:

写出约束的变分表达式:

写表达式的E-L方程:

化简可得:

即圆的微分方程,其中 $a-x$对应到 $\Delta x$, $\lambda$对应圆的半径。

最速降线问题

20190607082634.png

需要找到能使小球从A滚落B所需时间$T$最短的$f$

写出滚落所需时间的变分表达式:

用引理写出的E-L方程:

化简后有$y(1+y’^2) = C’$

解:

上式是一个三角函数,设$x$是关于$x(\theta)$的函数,$y’ = \cot \theta = \frac{\cos \theta}{\sin \theta}$。
由于$y’$是关于x的微分,所以不能求出$y’$关于$\theta$的方程,把$y’$代入上式:


$x$的$\theta$表示

转换成$x$关于$\theta$微元的表达式

$x$关于$\theta$的积分有:

积分可得:

化简得:


$y$的$x$、$y$表示

$\theta$角的变量表示

用$a$来代替$\frac{C}{2}$,由于 $y = C \sin ^2 \theta$,有 $\sin \theta = \sqrt{\frac{y}{2a}}$、 $\cos \theta = \sqrt{\frac{2a-y}{2a}}$

代回原式有:

2.4.Euler-lagrange方程的应用
3.1.拉格朗日乘子法
3.2. 泛函拉格朗日乘子法(一)
3.3. 泛函拉格朗日乘子法(二)
最速降线 与 第一次接触泛函

泛函、变分和欧拉-拉格朗日方程

Posted on 2019-06-07 | Edited on 2019-06-08 | In math

泛函

又被称为函数的函数,是将函数映射成数的方法。
传统的函数将数映射成数 $x -> f(x) -> y$;
泛函将 函数映射成数 $f(x) -> g(f) -> y$;

丢一些数进函数,得到一个数
丢一些方程进泛函,得到一个数

变分

用于分析一个泛函被扰动时的变化
相当于对一个泛函做微积分
变分法的关键定理是欧拉-拉格朗日方程。它对应于泛函的临界点。

变分的框架通常这样表示:

例如在最速降线问题中:
20190607082634.png

$f(x)$是小球的下落轨道
$f(x)’$是小球下落轨道的导数
$x$是小球的横向坐标
$T$代表从A落到B点所需时间

需要找到能使小球从A滚落B所需时间$T$最短的$f$

其中时间的表达式可以写成

也就是距离微元除以当前速度的积分,将问题变为一个关于$f$, $f’$的积分问题。
在最速降线问题中仅涉及$f$, $f’$

E-L方程

欧拉-拉格朗日方程 用于求泛函极值

说明

在函数中,我们可以通过求函数导数等于零,求出局部极值。这意味着在该变量附近做微小的扰动,会出现函数值达不到极值的现象。

同样的,假设在泛函中的极值处,$f_0(x)$是最理想的解,如果对$f_0(x)$做微小的扰动$f_0(x)+\eta (x)$,会出现泛函数值达不到极值的现象。
表示为:

构建

我们用 $\epsilon k(x)$ 来代替 $\eta (x)$,其中 $\epsilon$ 代表一个很小的标量,$k(x)$代表任意函数。
可以得到:

将其转化为关于$\epsilon$的函数问题,我们需要证明:
在对于任意$k(x)$,导数$A(\epsilon)’ = 0$ 在 $\epsilon = 0$上取到。
其中扰动$k(x)$的两端同$f(x)$重叠不移动。
表示为:

这是经典的单值函数求极值问题

推导

$f_1(x) = f_0(x) + \epsilon k(x)$,用$f_1$来表示

由于是在这里积分求导是线性的,将其互换转入积分的内部:

根据积分链式求导,求关于$\epsilon$的偏导有:

根据积分分部求导 $(ab)’= ab’ + b’a$:

由于在端点 $x_1$,$x_2$处,有约束所以$k(x_1) = k(x_2) = 0$:

可以得出E-L方程:

在满足该方程的条件下 $f_1(x)$ 是泛函极值函数
即:解函数相对于表达式的偏导 = 解函数导数相对于表达式的偏导变化率

引理

如果$F(f, f’, x) = F(f, f’)$ E-L 方程可以写成:

可以看出方程的导数在极值处为零,方程等于常数。
即:解函数导数相对于表达式的偏导 * 解函数导数 - 表达式 = 常数

最速降线 与 第一次接触泛函
2.3.Euler-lagrange方程的推导

拉格朗日乘子法(二)

Posted on 2019-06-05 | Edited on 2020-06-30 | In ml

Lagrange_portrait.jpg
Joseph Louis Lagrange

多个约束条件

引言

现在我们来看看,在一般情况下,当我们在 k个约束条件下:$g_i(x_1, …, x_n) = 0$,其中 $i$ 从 $1$到$k$ ,求最小化 $n$个变量的函数$f(x_1, …, x_n)$。拉格朗日函数和前文一样,除了每个约束有不同的$\lambda$。
约束:

(我们将$j$用于$k$作为约束索引,将$i$用于$n$作为变量的索引$x_i$。)约束最小值出现在所有变量对$L$的偏导数为零的点上。

简单例子

我们将使用一个相对简单的例子来说明方法:我们试图最小化 $x_1^2 + x_2^2 + x_3^2$
有两个约束条件:$x_1 = 1$ 和 $x_2 = 1$
Lagrangian: $x_1^2 + x_2^2 + x_3^2 - \lambda_1 (x_1 - 1) - \lambda_2 (x_2 - 1)$
它的偏导数是:

解

将它们全部设置为零得到答案:$(x_1, x_2, x_3) = (1, 1, 0)$ 和 $\lambda_1 = \lambda_2 = 2$.

在一个约束情形中,拉格朗日乘子方程等价于矢量方程 $\nabla f = \lambda \nabla g$
对于多个约束,相应的向量方程是:

解释

上述等式将得出以下事实:对于变量 $i$,当 成立时有 ,因此把($i$从$1$到$n$)偏导数置为零等效于上述向量方程。注意,将偏导数$\partial L / \partial \lambda_j$等于零只会强化$g_j(x_1, …, x_n) = 0$的约束。

如何相切

在一个约束情形中,找到点是有用的, $\nabla f = \lambda \nabla g$因为这意味着水平曲线$f$ 与水平曲线$g$相切。在多重约束的情况下,它并不那么简单。单个约束$g_i$的水平表面不一定与$f$约束最小值处的水平表面相切。(在上面的示例中,约束平面$x_1 = 1$与$f$球体的水平面$x_1^2 + x_2^2 + x_3^2 = 2$在最佳点处相交$(1, 1, 0)$。)相反,事实证明,所有$g_i$水平面的交点都与$f$水平面的相切。

为了更好的理解,让我们直接看$x$的小扰动对 $f$和约束方程$g_j$的影响,有$x = (x_1, …, x_n)$,同时使$\Delta x = (\Delta x_1, …, \Delta x_n)$我们有:

条件

如果更改$x$,有扰动$\Delta x$ 能保持所有$g_j$约束方程有相同的(一阶导),同时引起$f(x)$的非零变化,则$x$不可能是受约束的局部最小值。因为在某些方向上沿的交点移动所有的水平曲线$g_j$都会导致$f$减少(或增加)。所以我们想要的条件是:

  1. 对于所有可能使 $\nabla g_j(x) \perp \Delta x$ ,($j$从$1$到$k$) 成立的 $\Delta x$, 有$\nabla f(x) \perp \Delta x\textrm{.}$

对每个$j$有$\nabla g_j(x) \perp \Delta x$, $\Delta x$在与$g_j$水平面相切的方向上。如果$\Delta x$在与所有的$g_j$水平面交点相切的方向上,那么每一个$j$都成立。条件一表示任何此类$\Delta x$也与水平面相切$f$。另一方面,拉格朗日乘子法强制执行的条件是:

  1. 存在 到 使得 .

令人高兴的是,事实证明条件1和2等价。

定理:条件1和2等价

证明

证明:(为什么现在我们一整天挥手都有严格的证据?有时最直观的论证就是证明;也许就是这种情况。)首先我们将证明2、1等价.假设对于每一个从到,有 , 。因为。所以 。这意味着 。

接下来我们将证明1意味着2,或等效地,不是2意味着不是1.否定2表示$\nabla f$不在向量的跨度内。让我们用$z$来表示 $\nabla f$ 在 $\nabla g_j$ 跨度内的投影,并设置$\Delta x = \nabla f - z$。我们将证明这是建立否定条件1的反例。

证否

我们知道 $\nabla f \neq z$ 所以有 $\Delta x \neq 0$,通过投影的定义,对每个$j$有$\Delta x \perp g_j$。此外,$\nabla f \cdot \Delta x = (z + \Delta x) \cdot \Delta x = z \cdot \Delta x + \Delta x \cdot \Delta x$,因为 $z$ 是在$g_j$域上垂直于$\Delta x$,同样的有$z \perp \Delta x$。
新增$z \cdot \Delta x = 0$ 和$\Delta x \cdot \Delta x \neq 0$ ,我们得到 $(z + \Delta x) \cdot \Delta x \neq 0$。 也就是说$\nabla f \cdot \Delta x \neq 0$,所以$\nabla f$不垂直$\Delta x$。由于$\Delta x$垂直于所有$\nabla g_j$,但不垂直$\nabla f$,所以条件一也被证否。我们假设条件2的否定,因此这表明不是2意味着不是1,或者等效地,1意味着2。

小结

现在我们已经看到拉格朗日乘子法通过找到 $x$ 一组 这样 的东西而发挥作用。这个等式意味着不存在局部变化 ,使一阶导数,符合所有约束但改变目标函数 $f$ 的值。因此满足该等式的值$x$是受约束的局部最小值或最大值的候选值。求解该向量方程等效于将拉格朗日函数的偏导数设置为零。

我希望能够说明拉格朗日乘子法的工作方式和原因,并稍使它们看起来不这么像魔术。

后记

感觉原文作者描述的非常严谨,有很多地方我没法跟上作者的思路。
就我个人较感性的理解

单约束的表达式中:

拉格朗日函数偏导为零,表明梯度$\nabla f=(\frac{\partial f}{\partial x}, \frac{\partial f}{ \partial y}) $ ,和梯度 $\nabla g=(\frac{\partial g}{\partial x}, \frac{\partial g}{ \partial y}) $ 成比例。
只有在切点处才有梯度重叠,才可以向量互相线性表示;
在切点处是局部的极值点,任何符合$g$的微小扰动$(\Delta x, \Delta y)$ 会导致函数$f$的增大或减小。
所以解$L$偏导等于零的方程组(2+1),可以得到候选极值点。

在多约束表达式中:

有多变量,多约束条件;可以认为是求解极值向量的问题
多约束的条件下,单条件相切并不一定是局部极值;
需要做到$f$与所有$g_i$的相交处相切,即在约束面上各方向目标函数偏导数为零处。
梯度的原理同单约束,梯度向量在各方向上成比例。

在局部最优解的向量上,符合所有约束$g$的微小扰动向量$(\Delta x_1, \Delta x_2, …\Delta x_n)$都会导致函数$f$的增大或减小。
所以解$L$偏导等于零的方程组(n+1),可以得到候选极值向量。


20190606145608.png

将目标函数约束到三维空间,超平面中的球体半径为所求目标函数的值。

20190606145519.png

在$(1, 1, 0)$处球体与约束平面相切,取到极值2。

https://danstronger.wordpress.com/2015/08/08/lagrange-multipliers/
https://jermmy.github.io/2017/07/27/2017-7-27-understand-lagrange-multiplier/
https://www.svm-tutorial.com/2016/09/duality-lagrange-multipliers/

拉格朗日乘子法(一)

Posted on 2019-06-04 | Edited on 2019-06-08 | In ml

Lagrange_portrait.jpg
Joseph Louis Lagrange

definition on Wikipedia:

In mathematical optimization, the method of Lagrange multipliers is a strategy for finding the local maxima and minima of a function subject to equality constraints. (Wikipedia)

拉格朗日乘子法 是一种在一个或多个约束条件下,局部最小化或最大化函数的方法。
例如:对变量 $x$ 和 $y$ 使 $x^2 + y^2$ 尽可能小,同时满足约束$xy = 1$。
以下是如何使用拉格朗日乘子法及其工作原理的解释:
这个解释(尤其是为什么它们的工作)只有一个约束要简单得多,所以我们将从一个直观的论证开始,然后在多个约束的情况下转向一个更严格的论证。这两种情况都需要熟悉偏导数和向量

一个约束条件

假设我们想要根据约束 $g(x, y) = 0$, 最小化函数 $f(x, y)$ 。
(现在我们将最小化两个变量的函数,但是该方法将自然地扩展到更多变量的函数,并且最大化的过程完全相同。)
对于上面的例子,$f(x, y) = x^2 + y^2$ 和 $g(x, y)=xy-1$ (因为 $xy - 1 = 0$ 等价 $xy = 1$ )。
为了解决这个问题,我们创建了一个 $L(x, y, \lambda)$ 名为 Lagrangian 的新函数。
它被定义为 $L(x, y, \lambda)= f(x,y) - \lambda g(x, y)$ ,其中 $\lambda$ 是一个称为拉格朗日乘子的新变量。
(有些人用 $+$,而不是 $-$ ,但这并没有改变定义,除了$\lambda$的符号发生变化。)
然后,我们取原始变量$x$ 、 $y$、 $\lambda$ 相对于 $L$ 的偏导数,将所有这些部分设置为零,并求解 $x$ 和 $y$ 。
对于上面给出的例子,我们有:

将所有部分设置为零并求解,我们得到它 $\lambda = 2$ 并且(x, y)是(1, 1)或者(-1, -1)。
实际上,这些点是受制于约束 $g(x, y) = 0$的 $f(x, y)$ 局部最小值。(在这种情况下,它们也是全局极小值,虽然通常不能保证。)

引言

为什么拉格朗日乘子法有效?
人们很容易认为我们可以通过找到一个不受约束 $L$ 的最小值, 来找到一个受约束的 $f$ 的最小值; 毕竟,我们将所有 $L$ 的分量设置为等于零。但这是错误的。解决方案 $(x, y, \lambda)$ 实际上,从来不是局部最小值或最大值,总是会有一个马鞍点对应到 $L$。那么为什么拉格朗日乘子法有效呢?答案与等高曲线和梯度有关。

lagrange1.png

等值曲线

函数的等值曲线[等高线]是函数等于常数值的点集。
(在三个维度中,它们被称为等值面,更一般地说,等值集合。)
在上面的图片中,红色圆是一些等值曲线 $f(x, y) = x^2 + y^2$(较大的圆对应于 $f$中更高的值)。
蓝色曲线是满足约束 $g(x, y) = 0$ 的点集,使其成为 $ g(x, y)$ 的一条等值曲线。

几何分析

约束最小化就是寻找蓝色曲线上红色谷中最低的点:每个红色曲线代表不同高度的谷。
事实证明,这极值点总是红色和蓝色等值曲线的相切点,例如上图中的黑点。
要了解原因,有必要查看曲线不相切的点,例如橙色点。由于红色和蓝色等值曲线在橙色点彼此不相切,它们彼此交叉。由于它们交叉,当沿着蓝色曲线在红色谷中向一个方向上移动时,红谷值向另一个方向移动向下移动。
换句话说,存在局部变化 $(x, y)$,在保持约束 $g(x, y) = 0$ 的情况下,导致目标函数$f(x, y)$减少,而相反的变化导致它增加。 因此交叉点不可能是受限制的最小值或最大值。由于最小值不能在等值曲线交叉的点处,因此它必须在它们相切的点处。在切点,当你沿着曲线 $g(x, y) = 0$ 移动时, $f(x, y)$ 是近似不变的一阶导数,因此它可能是最小值或最大值。(它可能也不是,但至少它可能是。)

数学分析

我们如何在数学上表达等值曲线 $f$ 和 $g$ 相切?这是梯度的来源。函数的梯度 $f$ 被写为 $ \nabla f$ 并定义为向量,其中每个分量是 $f$ 相对于相应变量的偏导数:$\nabla f = (\partial f / \partial x, \partial f / \partial y)$。梯度具有对我们非常有用的属性:$f$ 的梯度总是垂直于 $f$ 给定的等值曲线$(x, y)$。要探究这个问题,我们定义 $(\Delta x, \Delta y)$ 是改变$(x, y)$的微元[small amount]。它将如何改变f$(x, y)$?首先,答案是:

如果$(\Delta x, \Delta y)$是在等值曲线的方向,我们将拥有 $ f(x + \Delta x, y + \Delta y) \approx f(x, y)$,这意味着 $\frac{\partial f}{\partial x}\Delta x + \frac{\partial f}{\partial y} \Delta y = 0 $ 。换句话说,$\nabla f$ 和 $(\Delta x, \Delta y)$ 的点积为零。由于 $(\Delta x, \Delta y)$在等值曲线的方向上,这意味着 等值曲线和梯度彼此垂直。

由于我们希望的等值曲线 $f$ 和 $g$ 为彼此相切,并且每个函数的梯度是垂直于它的等值曲线中,我们希望梯度以在相同的方向(或沿相反方向)指向。如果一个是另一个的标量倍数,则两个向量指向相同的方向。 这个标量将成为拉格朗日乘子,我们称之为$ \lambda: \nabla f = \lambda \nabla g$。该向量方程扩展为每个 $x$ 和的一个方程 $y$。将约束本身添加到我们的方程组中,我们得到:

\begin{array}{rcl}\frac{\partial f}{\partial x}&=&\lambda \frac{\partial g}{\partial x}\ \frac{\partial f}{\partial y}&=&\lambda \frac{\partial g}{\partial y} \ g(x, y) & = & 0 \end{array}

小结

Lagrange multipliers方法就是产生这些方程并求解它们。然而它通常用拉格朗日函数来描述 $ L(x, y, \lambda) = f(x, y) - \lambda g(x, y)$。将 $x$, $y$, $\lambda$ 关于Lagrangian的偏导数,写成以上例子的形式。例如,$ \partial L / \partial x = \partial f / \partial x - \lambda \partial g / \partial x$。 将这个值设为零就可以得到例子中的第一个方程。最后还有一个等式,$ \partial L / \partial \lambda = -g(x, y)$。如果你愿意,你根本就不需要担心Lagrangian,你只需要找到一个点$(x, y)$ 和标量 $\lambda$,使$ \nabla f = \lambda \nabla g$ 满足约束条件。这些点将是约束最小值(或最大值)的候选值。

总之,约束极小值和极大值出现在约束函数的等值曲线 $g$与 目标函数的等值曲线 $f$的相切的点处。
当 $ \nabla f = \lambda \nabla g$ 时,有以上例子中的方程式成立。拉格朗日函数$L$用一个函数的偏导数将这些方程统一起来。

后记

在切点位置两等值曲线方向平行,考虑到梯度和等值曲线垂直,那么可以用梯度平行来求切点位置。

切点 -> 变量偏导比例相等 -> 梯度方向相同 -> 梯度模成比例 -> 候选极值


20190605171448.png

20190605181854.png

20190605172014.png

https://danstronger.wordpress.com/2015/08/08/lagrange-multipliers/
https://jermmy.github.io/2017/07/27/2017-7-27-understand-lagrange-multiplier/
https://www.svm-tutorial.com/2016/09/duality-lagrange-multipliers/

1…91011…29

Leon

282 posts
20 categories
58 tags
GitHub
Links
  • clock
  • typing-cn
  • mathjax
  • katex
  • cron
  • dos
  • keyboard
  • regex
  • sql
  • toy
© 2017 – 2024 Leon
Powered by Hexo v3.9.0
|
Theme – NexT.Muse v7.1.2