mxxhcm's blog

  • 首页

  • 标签

  • 分类

  • 归档

python numpy

发表于 2019-03-18 | 更新于 2019-12-17 | 分类于 python

numpy.ndarray

np.ndarray的属性

  • ndarray.shape # shape
  • ndarray.ndim # 维度
  • ndarray.size # 元素个数
  • ndarray.itemsize # size of the element in array
  • ndarray.dtype # type of the number in array,dtype可以是’S’,int等
  • ndarray.T # 转置
1
array[array>0].size    #统计一个数组有多少个非零元素,不论array的维度是多少

常用方法

  • ndarray.transpose(axes) # 矩阵转置
  • ndarray.all()
  • ndarray.any()
  • ndarray.reshape(shape[, order]) # reshape
  • ndarray.resize(new_shape[, refcheck]) # resize
  • ndarray.tolist() # 转换为list
  • ndarray.squeeze([axis]) # 去掉为1的维度
  • ndarray.repeat(repeats, axis=None) # 重复数组元素,默认进行flatten返回一个一维数组
  • ndarray.flatten([order]) # flatten
  • ndarray.nonzero() # 返回非零元素的索引
  • ndarray.astype(‘S’) # 将整形数组改为字符型
  • ndarray.mean(axis=None, dtype=None, out=None) # 返回数组元素均值
  • ndarray.argmin(axis=None, out=None) # 返回最小元素的索引。
  • ndarray.argmax(axis=None, out=None) # 返回最大元素索引值
  • ndarray.min(axis=None, out=None) # 返回最小值
  • ndarray.round(decimals=0, out=None) # 将数组中的元素按指定的精度进行四舍五入

其他方法

  • ndarray.ptp()
  • ndarray.clip()
  • ndarray.swapaxes(axis1, axis2)
  • ndarray.var(axis=None, dtype=None, out=None, ddof=0) # 返回数组的方差
  • ndarray.std(axis=None, dtype=None, out=None, ddof=0) # 返回数则的标准差
  • ndarray.swapaxes(axis1, axis2) : 交换两个轴的元素后的矩阵.
  • ndarray.ravel([order]) :返回为展平后的一维数组.
  • ndarray.take(indices, axis=None, out=None, mode=’raise’):获得数组的指定索引的数据,如:
  • numpy.put(a, ind, v, mode=’raise’):用v的值替换数组a中的ind(索引)的值。Mode可以为raise/wrap/clip。Clip:如果给定的ind超过了数组的大小,那么替换最后一个元素。
  • numpy.tile(A, reps):根据给定的reps重复数组A,和repeat不同,repeat是重复元素,该方法是重复数组。
  • ndarray.prod(axis=None, dtype=None, out=None):返回指定轴的所有元素乘机
  • ndarray.cumprod(axis=None, dtype=None, out=None):返回指定轴的累积,如下:
  • ndarray.cumsum(axis=None, dtype=None, out=None):返回指定轴的元素累计和。
  • ndarray.sum(axis=None, dtype=None, out=None):返回指定轴所有元素的和
  • ndarray.trace(offset=0, axis1=0, axis2=1, dtype=None, out=None):返回沿对角线的数组元素之和
  • ndarray.diagonal(offset=0, axis1=0, axis2=1):返回对角线的所有元素。
  • ndarray.compress(condition, axis=None, out=None):返回指定轴上条件下的切片。

numpy数组初始化

  • numpy.array()
  • numpy.zeros()
  • numpy.empty()
  • numpy.random()

numpy.array()

函数原型

1
2
3
4
5
6
7
8
np.array(
object,
dtype=None,
copy=True,
order=False,
subok=False,
ndim=0
)

numpy.zeros()

函数原型

1
2
3
4
5
np.zeros(
shape,
dtype=float,
order='C'
)

代码示例

代码地址

1
2
3
4
5
6
7
8
9
10
11
np.zeros((3, 4),dtype='i')
```

### numpy.empty()
#### 函数原型
``` python
np.empty(
shape,
dtype=float,
order='C'
)

代码示例

代码地址

1
np.empty((3, 4),dtype='f')

numpy.random

numpy.random.randn()

返回标准正态分布的一个样本
numpy.random.randn(d0, d1, …, dn)
例子

1
np.random.randn(3,4)

array([[ 0.47203644, -0.0869761 , -1.02814481, -0.45945482],
[ 0.34586502, -0.63121119, 0.35510786, 0.82975136],
[-2.00253326, -0.63773715, -0.82700167, 1.80724647]])

numpy.random.rand()

创建一个给定shape的数组,从区间[0,1)上的均匀分布中随机采样

create an array of the given shape and populate it with random samples from a uniform disctribution over [0,1)

numpy.random.rand(d0,d1,…,dn)
例子

1
np.random.rand(3,4)

numpy.random.random()

返回区间[0.0, 1.0)之间的随机浮点数

return random floats in the half-open interval [0.0,1.0)

numpy.random.random(size=None)
例子

1
np.random.random((3,4))
Note

注意,random.random()和random.rand()实现的功能都是一样的,就是输入的参数不同。见参考文献[1]。

numpy.random.ranf()

我觉得它和random.random()没啥区别

numpy.random.randint()

return random integers from low(inclusive) to high(exclusive),[low,high) if high is None,then results are from [0,low)

numpy.random.randint(low,high=None,size=None,dtype=‘l’)
例子

1
2
np.random.randint(3,size=[3,4])
np.random.randint(4,6,size=[6,2])

numpy.random.RandomState()

class numpy.random.RandomState(seed=None)

这是一个类,给定一个种子,它接下来产生的一系列随机数都是固定的。每次需要重新产生随机数的时候,就重置种子。
通过一个例子来看:

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
import numpy as np
rdm = np.randrom.RandomState()
for i in range(3):
rdm.seed(3)
print(rdm.rand())
print(rdm.rand())
print(rdm.rand())
print("\n")
# 0.9670298390136767
# 0.5472322491757223
# 0.9726843599648843

# 0.9670298390136767
# 0.5472322491757223
# 0.9726843599648843

# 0.9670298390136767
# 0.5472322491757223
# 0.9726843599648843

# 0.9670298390136767
# 0.5472322491757223
# 0.9726843599648843

# 0.9670298390136767
# 0.5472322491757223
# 0.9726843599648843

创建bool类型数组

np.ones([2, 2], dtype=bool)
np.zeros([2, 2], dtype=bool)

np.random

np.random.binomial

函数原型

1
2
3
4
5
numpy.random.binomial(
n,
p,
size=None
)

介绍

二项分布,共有三个参数,前两个是必选参数,第三个是可选参数。$n$是实验的个数,比如同时扔三枚硬币,这里就是$n=3$,$p$是为$1$的概率。$size$是总共进行多少次实验。
返回值是在每次试验中,trival成功的个数。如果是一个scalar,代表$size=1$,如果是一个list,代表$size\gt 1$。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np

for i in range(10):
rand = np.random.binomial(2, 0.9)
print(rand)
# 可以看成扔2个硬币,每个硬币正面向上的概率是0.9,最后有几个硬币正面向上。
# 2
# 2
# 2
# 2
# 2
# 2
# 2
# 1
# 1
# 2

rand = np.random.binomial(3, 0.9, 5)
print(rand)
# 可以看成扔3个硬币,每个硬币正面向上的概率是0.9,最后有几个硬币正面向上。一共进行5次实验。
# [2 2 3 3 2]

np.random.choice

函数原型

1
2
3
4
5
6
numpy.random.choice(
a, # 1d array或者int,如果是一个数组,从其中生成样本;如果是一个整数,从np.arange(a)中生成样本
size=None, # output shape,比如是(m, n, k)的话,总共要m*n*k个样本,默认是None,返回一个样本。
replace=True, # 是否使用replacement,设置为False的话所有元素不重复。
p=None # 概率分布,相加必须等于1,默认是从一个均匀分布中采样。
)

代码示例

代码地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np

a0 = np.random.choice([8, 9, -1, 2, 0], 3)
print(a0)

# 从np.arange(5)从使用均匀分布采样一个shape为4的样本
a1 = np.random.choice(5, 4)
print(a1)

a2 = np.random.choice(5, 8, p=[0.1, 0.2, 0.5, 0.2, 0])
print(a2)

# replace 设置为False,相当于np.random.permutation()
a3 = np.random.choice([1, 2, 3, 8, 9], 5, replace=False)
print(a3)

np.random.permutation

函数原型

1
2
3
np.random.permutation(
x # int或者array,如果是int,置换np.arange(x)。如果是array,make a copy,随机打乱元素。
)

简介

对输入序列进行排列组合,如果输入是多维的话,只会在第一维重新排列。

代码示例

代码地址

1
2
3
4
5
6
7
8
9
10
11
import numpy as np


a1 = np.random.permutation(9)
print(a1)

a2 = np.random.permutation([1, 2, 4, 9, 8])
print(a2)

a3 = np.random.permutation(np.arange(9).reshape(3, 3))
print(a3)

np.random.normal

函数原型

1
2
3
4
5
numpy.random.normal(loc=0.0, scale=1.0, size=None)  
loc:float,正态分布的均值,对应着整个分布的center
scale:float,正态分布的标准差,对应于分布的宽度,scale越大越矮胖,scale越小,越瘦高
size:int or tuple of ints,输出的shape,默认为None,只输出一个值
np.random.randn(size)相当于np.random.normal(loc=0, scale=1, size)

np.argsort

函数原型

numpy.argsort(a, axis=-1, kind=‘quicksort’, order=None)
axis:对哪个axis进行排序,默认是-1

功能

将数组排序后(默认是从小到大排序),返回排序后的数组在原数组中的位置。

参考文献

1.https://stackoverflow.com/questions/47231852/np-random-rand-vs-np-random-random
2.https://stackoverflow.com/questions/21174961/how-to-create-a-numpy-array-of-all-true-or-all-false
3.https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.choice.html
4.https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.permutation.html
5.https://www.cnblogs.com/bonelee/p/7253966.html

python jupyter notebook笔记

发表于 2019-03-18 | 更新于 2019-12-17 | 分类于 python

一、安装和运行

1.安装

Anaconda安装

Anaconda自身已经集成了jupyter包,所以如果没有装python的话,可以选择安装Anaconda集成环境

pip安装

~#:pip install jupyter

2.运行

~#:jupyter notebook

3.远程访问

(1).直接使用命令

这种方法是建立了一个session,会有一个token,这个会话结束之后,这个token就无效了,需要再重现建立新的session

a.在前台运行以下命令

~#:jupyter notebook --ip=your_server_ip
输出如下

复制这个url到你的客户端浏览器,就可以直接访问服务器端。

b.后台运行

~#:nohup jupyter notebook --ip=10.4.21.214 &

(2).创建配置文件

a.服务器端设置密码

这里是使用notebook的passwd()函数生成自己设置密码的sha1哈希值。

1
2
from notebook.auth import passwd
passwd()

输入两边自己设置的密码,然后将哈希值复制到下面的配置文件中即可。

b.服务端设置配置文件

~#:jupyter notebook --generate-config
~#:vim ~/.jupyter/jupyter_notebook_config.py

1
2
3
4
c.NotebookApp.ip='localhost'
c.NotebookApp.password=u'sha1:...'
c.NotebookApp.open_browser=False
c.NotebookApp.port=8888(your_port)
c.服务器端启动

~#:jupyter notebook

d.客户端访问

http://your_server_ip:port
输入密码即可

二、使用

1.创建新的文档

三、快捷键

Jupyter Notebook 有两种键盘输入模式。编辑模式,允许你往单元中键入代码或文本;这时的单元框线是绿色的。命令模式,键盘输入运行程序命令;这时的单元框线是灰色。

1.命令模式 (按键 Esc 开启)

Enter : 转入编辑模式
Shift-Enter : 运行本单元,选中下个单元
Ctrl-Enter : 运行本单元
Alt-Enter : 运行本单元,在其下插入新单元
Y : 单元转入代码状态
M :单元转入markdown状态
R : 单元转入raw状态
1 : 设定 1 级标题
2 : 设定 2 级标题
3 : 设定 3 级标题
4 : 设定 4 级标题
5 : 设定 5 级标题
6 : 设定 6 级标题
Up : 选中上方单元
K : 选中上方单元
Down : 选中下方单元
J : 选中下方单元
Shift-K : 扩大选中上方单元
Shift-J : 扩大选中下方单元
A : 在上方插入新单元
B : 在下方插入新单元
X : 剪切选中的单元
C : 复制选中的单元
Shift-V : 粘贴到上方单元
V : 粘贴到下方单元
Z : 恢复删除的最后一个单元
dd : 删除选中的单元
Shift-M : 合并选中的单元
Ctrl-S : 文件存盘
S : 文件存盘
L : 转换行号
O : 转换输出
Shift-O : 转换输出滚动
Esc : 关闭页面
Q : 关闭页面
H : 显示快捷键帮助
I,I : 中断Notebook内核
0,0 : 重启Notebook内核
Shift : 忽略
Shift-Space : 向上滚动
Space : 向下滚动

2.编辑模式 ( Enter 键启动)

Tab : 代码补全或缩进
Shift-Tab : 提示
Ctrl-] : 缩进
Ctrl-[ : 解除缩进
Ctrl-A : 全选
Ctrl-Z : 复原
Ctrl-Shift-Z : 再做
Ctrl-Y : 再做
Ctrl-Home : 跳到单元开头
Ctrl-Up : 跳到单元开头
Ctrl-End : 跳到单元末尾
Ctrl-Down : 跳到单元末尾
Ctrl-Left : 跳到左边一个字首
Ctrl-Right : 跳到右边一个字首
Ctrl-Backspace : 删除前面一个字
Ctrl-Delete : 删除后面一个字
Esc : 进入命令模式
Ctrl-M : 进入命令模式
Shift-Enter : 运行本单元,选中下一单元
Ctrl-Enter : 运行本单元
Alt-Enter : 运行本单元,在下面插入一单元
Ctrl-Shift-- : 分割单元
Ctrl-Shift-Subtract : 分割单元
Ctrl-S : 文件存盘
Shift : 忽略
Up : 光标上移或转入上一单元
Down :光标下移或转入下一单元

python h5py笔记

发表于 2019-03-18 | 更新于 2019-12-17 | 分类于 python

python包安装

~$:pip install h5py

简介

创建和打开h5py文件

f = h5py.File(“pathname”,“w”)
w create file, truncate if exist
w- or x create file,fail if exists
r readonly, file must be exist r+ read/write,file must be exist
a read/write if exists,create othrewise (default)

删除一个dataset或者group

1
del group["dataset_name/group_name"]

dataset

什么是dataset

datasets和numpy arrays挺像的

创建一个dataset

1
2
3
f = h5py.File("pathname","w")
f.create_dataset("dataset_name", (10,), dtype='i')
f.create_dataset("dataset_name", (10,), dtype='c')

第一个参数是dataset的名字, 第二个参数是dataset的shape, dtype参数是dataset中元素的类型。

如何访问一个dataset

1
2
dataset = f["dataset_name"]                           # acess like a python dict
dataset = f.create_dateset("dataset_name") # or create a new dataset

dataset的属性

dataset.name #输出dataset的名字
dataset.tdype #输出dataset中elements的type
dataset.shape #输出dataset的shape
dataset.value
dataset doesn’t hava attrs like keys,values,items,etc…

给h5py dataset复制numpy array

1
2
array = np.zero((2,3,4)
h['array'] = array # in h5py file, you need't to explicit declare the shape of array, just assign it an object of numpy array

group

什么是group

group和字典挺像的

创建一个group

1
2
3
group = f.create_group("group_name")    #在f下创建一个group
group.create_group("group_name") #在group下创建一个group
group.create_dataset("dataset_name") #在group下创建一个dataset

访问一个group(the same as dataset)

1
2
group = f["group_name"]                           # acess like a python dict
group = f.create_dateset("group_name") # or create a new group

group的属性和方法

group.name #输出group的名字
以下内容分为python2和python3版本

python 2 版本

group.values() #输出group的value
group.keys() #输出gorup的keys
group.items() #输出group中所有的item,包含group和dataste

python 3 版本

list(group.keys())
list(group.values())
list(group.items())

属性

设置dataset属性

dataset.attrs[“attr_name”]=“attr_value” #设置attr
print(dataset.attrs[“attr_name”]) #访问attr

设置group属性

group.attrs[“attr_name”]=“attr_value” #设置attr
print(group.attrs[“attr_name”]) #访问attr

numpy and h5py

1
2
3
4
5
f = h5py.File(pathname,"r")

data = f['data'] # type 是dataset
data = f['data'][:] #type是numpy ndarray
f.close()

参考文献

1.http://docs.h5py.org/en/latest/index.html
2.https://stackoverflow.com/questions/31037088/discovering-keys-using-h5py-in-python3

MongoDB笔记

发表于 2019-03-18 | 更新于 2020-04-20 | 分类于 数据库

数据库的安装

自行下载安装包并安装

数据库的运行和连接,以及以下简单的使用

一些简单的操作

1
2
3
4
5
6
7
8
9
10
11
# 连接mongodb数据库
mongo (database_name) # 如果不输入数据库名会默认连接到mongodb自带的一个数据库test,如果指定了数据库名就会连接到该数据库

#切换数据库
use database_name;

#查看所有的数据库
show databases;

#查看所有的collection
show collections;

使用python代码中连接到数据库

1
2
3
4
5
6
7
8
9
import pymongo

connection = pymongo.MongoClient('localhost', 27017)

db = connection.test # db指向test数据库
collection = db.mycollection

items = collection.find()
print(items['key'])

C++ 访问mongodb

安装参考[1]。

CRUD操作

id的构成 12 bytes hex

4+3+2+3
timestamp + mac address + pid + counter
timestamp是unix timestamp,mac address 是 mongd运行的网卡mac address,pid是process id,

create document

create one document(insertOne)

1
db.collection_one.insertOne({"key_one":"value","key_two":"value"})

create many documents(有order,insertMany)

1
2
3
4
5
6
db.collection_one.insertMany(
[
{"key_one":"value","key_two":"value"},
{"key_one":"value","key_two":"value"},
{"key_one":"value","key_two":"value"}
])

create many documents(无order,insertMany)

1
2
3
4
5
6
7
db.collection_one.insertMany(
db.collection_one.insertMany(
[
{"key_one":"value","key_two":"value"},
{"key_one":"value","key_two":"value"},
{"key_one":"value","key_two":"value"}
] , {"ordered":false})

upsert

第一个参数是一个filter选择合适的 document,第二个参数是一个更新操作for the documents were selected,第三个参数是 that if there is no matching result,if the value of upsert is true,then insert a new document,else do nothing.

1
2
db.collection_one.insertMany(
db.movieDetails.updateOne({ name:"mxxhcm"}, { \$set:{lover:"mahuihui"} } , {upsert : true})

有无order的区别

有order的话遇到inset错误就会停下来,没有order的话在插入document的时候,遇到错误会跳过该条语句执行下一条语句。

read documents(query documents)

link:
https://docs.mongodb.com/manual/reference/operator/query/

查找document

查找collection_one这个collection中所有的document

1
db.collection_one.find()

查找collection_one这个collection中满足{}中条件的collection,{}中的条件需要满足anded

1
db.collection_one.find({})

pretty()表示以规范的格式展现出来查询结果

1
db.collection_one.find().pretty()

findOne表示只展示出第一条结果

1
db.collection_one.findOne()

满足{}中条件的第一条结果

1
db.collection_one.findOne({})

对document进行计数

1
db.collection_one.count()

设置查找的条件(equality match)

a.scalar equality match
1
db.collection_one.find({"key":"value","key","value"})
b.nested documents equality match
1
db.collection_one.find({"key.key2.key3":"value"})
c.equality matches on arrays
entire array value match
1
db.collection_one.find({key:[value1,value2]})
any array element fileds match a specfic value
1
db.collection_one.find({key:"value2"})
a specfiec element fields match a specfic value
1
db.collection_one.find({key.0:"value1"})

(4)cursor

(5)projection

by default,mongodb return all fields in all matching documents for query.
Projection are supplied as the second argument
db.collection_one.find({“key1”:“value”,“key2”,“value”},{“key1”:1,“key2”:1,“key3”:0,“key4”:0}).pretty()

(6)comparison operation

$eq
$gt
$gte
$lt
$lte
$ne
$in
$nin

a.在某个范围内
1
db.movieDetails.find({ runtime : { \$gt: 70,  \$lte:100 } }).pretty()
b.不等于($ne)
1
db.movieDetails.find({ rated : { \$ne:"unrated" } }).pretty()
c.在($in)
1
db.movieDetails.find({rated : { \$in : ["G","PG","PG-13"] }  }).pretty()

(7)element operator

a.存在某个filed($exists)
1
db.movieDetail.find( { filed_name : { \$exists: true|false } } ).pretty()
b.某个字段的类型($type)
1
db.movieDetail.find( { filed_name : { \$type :"string"} }).pretty()

(8)logical operator

$or
$and
$not
$nor

a.逻辑或($or)

$or需要数组作为参数

1
db.movieDetails.find( { \$or: [ { field_one : {\$type : "string"} } , {field_two : {\$exist: "name" } } ] } ).pretty()
b.逻辑与($and)

$and操作支持我们在同一个filed指定多个约束条件

1
db.movieDetails.find({ \$and: [ {field_one: {\$ne :null} } , { field_one: {\$gt:60, \$lte: 100} } ] }).pretty()

(9)regex operator

1
db.movieDetails.find({ "awards.text": { \$regex: /^Won\s/}  }).pretty()

(10)array operator

$all
$size
$elementMatch

a.all
1
2
db.movieDetails.find({genres : {\$all :["comedy","crime","drama"]} }).pretty()
db.movieDetails.find({genres : ["comedy","crime","drama"] }).pretty()

上面两个式子是有区别的,第一个式子会匹配genres中包含"comedy",“crime”,“drama"的document
而第二个只会匹配genres为"comedy”,“crime”,"drama"的document。

b.size
1
db.movieDetails.find({country : {\$size : 3} }).pretty()
c.elementMatch
1
db.movieDetails.find({ boxOffice: { country: "UK", revenue: { \$gt: 15 } } })

9.update documents

link:
https://docs.mongodb.com/manual/reference/operator/update/

(0)some update operator

1
db.movieDetails.updateOne( { name : "mxxhcm" } , { \$inc : { age: 1} })

(1)updateOne

a.update for scalar fields

$set

1
db.movieDetails.updateOne( { name : "mxxhcm" } , { \$set : { age: 19} })

$unset

1
db.movieDetails.updateOne( { name : "mxxhcm" } , { \$unset : { age: 19} })

$inc
age后是在原来的age上加的数值

1
db.movieDetails.updateOne( { name : "mxxhcm" } , { \$set : { age: 19} })

updateOne has two arguments, the first one is a selector,the second argument is how we want to update the document.

b.update for array fields

$push

1
2
3
4
5
6
7
8
9
10
11
db.movieDetails.updateOne({name:"mxxhcm"} , {\$push: { reviews: { key1:value,key2:value...}  }  } )
db.movieDetails.updateOne({name:"mxxhcm"} , {\$push: { reviews:
{ \$each: [{ key1:value,key2:value...} , {key1:value,key2:value...} ] }
} } )
db.movieDetails.updateOne({name:"mxxhcm"} , {\$push: { reviews:
{ \$each: [{ key1:value,key2:value...} , {key1:value,key2:value...} ] , \$slice:3 }
} } )
db.movieDetails.updateOne({name:"mxxhcm"} , {\$push: { reviews:
{ \$each: [{ key1:value,key2:value...} , {key1:value,key2:value...} ] , \$position:0,
\$slice:3 }
} } )

(2)updateMany

the same as updateOne

(3)replaceOne

1
db.movieDetail.replcaeOne({},{})

the first argument is a filter,the second argument is the thing that replace what the filter choose,it can be a document,or a variable point to a document.

10. using mongdb by pymongo

见代码

(1)sort,skip,limit

sort > skip > limit

1
2
3
4
5
cursor.sort('student_id',pymongo.ASCENDING).skip(4).limit(3)
in python file:
cursor.sort( [ ('student_id',pymongo.ASCENDING) , ('score',pymongo.DESCENDING) ] ).skip(4).limit(3)
in mongo shell:
cursor.sort( [ {'student_id':1}, {'score',-1)} ] ).skip(4).limit(3)

####(2)find,find_one,cursors
####(3)project
####(4)regex
####(5)insert
####(6)update
####(7)
There is a intervening between find and update,so maybe you find and update is not the same one.

参考文献

1.http://mongocxx.org/mongocxx-v3/installation/

神经网络-激活函数

发表于 2019-03-14 | 更新于 2019-12-17 | 分类于 机器学习

激活函数的一些问题

为什么要使用non-linear激活函数不使用linear激活函数?

fnn
给定一个如图所示的前馈神经网络。有一个输入层,一个隐藏层,一个输出层。输入是$2$维的,有$4$个隐藏单元,输出是$2$维的。
则:$ \hat{f}(x) = \sigma(w_1x+b_1)w_2 + b_2$
这里$\sigma$是一个线性的激活函数,不妨设$\sigma(x) = x$。
那么就有:
\begin{align*}
\hat{f}(x) &= \sigma(w_1x+b_1)w_2 + b_2\
&= (w_1x+b_1)w_2 + b_2\
&= w_1w_2x + w_2b1 + b_2\
&= (w_1w_2) x + (w_2b1 + b_2)\
&= w’ x + b’
\end{align*}
因此,当使用线性激活函数的时候,我们可以把一个多层感知机模型化简成一个线性模型。当使用线性激活函数时,增加网络的深度没有用,使用线性激活函数的十层感知机和一层感知机没有区别,并不能增加网络的表达能力。因为任意两个仿射函数的组合还是仿射函数。

为什么ReLU激活函数是non-linear的?

ReLU的数学表达形式如下:
$$g(x) = max(0, x)$$
首先考虑一下什么是linear function,什么是non-linear function。在微积分上,平面内的任意一条直线是线性函数,否则就是非线性函数。
考虑这样一个例子,输入数据的维度为$1$,输出数据的维度也为$1$,用$g(ax+b)$表示ReLU激活函数。如果我们使用两个隐藏单元,那么$h_1(x) = g(x)+g(-x)$可以用来表示$f(x)=|x|$,而函数$|x|$是一个非线性函数,函数图像如下所示。
f(x)=|x|
我们还可以用ReLU逼近二次函数$f(x) = x^2$,如使用函数$h_2(x) = g(x) + g(-x) + g(2x-2) + g(2x+2)$逼近二次函数,对应的图像如下。
h_2(x)
使用的项越多,最后近似出来的图像也就和我们要逼近的二次函数越像。
同理,可以使用ReLU激活函数去逼近任意非线性函数。

为什么ReLU比sigmod还有tanh激活函数要好?

ReLU收敛的更快,因为梯度更大。
当CNN的层数越来越深的时候,实验表明,使用ReLU的CNN要比使用sigmod或者tanh的CNN训练的更容易,更快收敛。
为什么会这样,目前有两种理论,见参考文献[4]。
第一个,$tanh(x)$有梯度消散问题(vanishing gradient)。当$x$趋向于$\pm\infty$时,$tanh(x)$的导数趋向于$0$。如下图所示。

Vanishing gradients occur when lower layers of a DNN have gradients of nearly 0 because higher layer units are nearly saturated at -1 or 1, the asymptotes of the tanh function. Such vanishing gradients cause slow optimization convergence, and in some cases the final trained network converges to a poor local minimum.

One way ReLUs improve neural networks is by speeding up training. The gradient computation is very simple (either 0 or 1 depending on the sign of x). Also, the computational step of a ReLU is easy: any negative elements are set to 0.0 – no exponentials, no multiplication or division operations.

tanh(x)
ReLU是non-saturating nonlinearity的激活函数,sigmod和tanh是saturating nonlinearity激活函数,会将输出挤压到一个区间内。

f是non-saturating 当且仅当$|lim_{z\rightarrow -\infty} f(z)| \rightarrow + \infty$或者$|lim_{z\rightarrow +\infty} f(z)| \rightarrow + \infty$

tanh和sigmod将输入都挤压在某一个很小的区间内,比如(0,1),输入发生很大的变化,经过激活函数以后变化很小,经过好几层之后,基本上就没有差别了。而当网络很深的时候,反向传播主要集中在后几层,而输入层附近的权值没办法好好学习。而对于ReLU来说,任意深度的神经网络,都不存在梯度消失。

第二种理论是说有一些定理能够证明,在某些假设条件下,局部最小就是全局最小。如果使用sigmod或者tanh激活函数的时候,这些假设不能成立,而使用ReLU的话,这些条件就会成立。

为什么发生了梯度消失以后训练结构很差?

我的想法是,

参考文献

1.https://stats.stackexchange.com/a/391971
2.https://stats.stackexchange.com/a/299933
3.https://stats.stackexchange.com/a/141978
4.https://stats.stackexchange.com/a/335972
5.https://stats.stackexchange.com/a/174438
6.https://stats.stackexchange.com/questions/391968/relu-vs-a-linear-activation-function
7.https://stats.stackexchange.com/questions/141960/why-are-rectified-linear-units-considered-non-linear
8.https://stats.stackexchange.com/questions/299915/how-does-the-rectified-linear-unit-relu-activation-function-produce-non-linear
9.https://stats.stackexchange.com/questions/226923/why-do-we-use-relu-in-neural-networks-and-how-do-we-use-it/226927#226927
10.https://www.zhihu.com/question/264163033
11.http://ai.stanford.edu/~amaas/papers/relu_hybrid_icml2013_final.pdf

CNN

发表于 2019-03-13 | 更新于 2019-12-17 | 分类于 机器学习

CNN

图片的表示

图像在计算机中是一堆按顺序排列的顺子,数值为0到255。0表示最暗,255表示最亮。我们可以把这堆数字用一个长长的一维数组来表示,但是这样会失去平面结构的信息,为保留该结构信息,我们通常会选择矩阵的表示方式,用一个nn的矩阵来表示一个图像。对于黑白颜色的灰度图来说,我们只需要一个nn的矩阵表示即可。对于一个彩色图像,我们会选择RGB颜色模型来表示。
在彩色图像中,我们需要用三个矩阵去表示一张图,也可以理解为一个三维张量,每一个矩阵叫做这张图片的一个channel。这个三维张量可以表示为(width,length,depth),一张图片就可以用这样一个张量来表示。

卷积神经网络(CNN)

作用

让权重在不同位置共享

filter和stride

filter又叫做kernel或者feature detector。filter会对输入的局部区域进行处理,filter处理的局部区域的范围叫做filter size。比如说一个filter的大小为(3,3),那么这个filter会一次处理width=3,length = 3的区域。卷积神经网络会用filter对整个输入进行扫描,一次移动的多少叫做stride。filter处理一次的输出为一个feature map。

depth

对于filter来说,我们一般说它的大小为(3,3)只说了它在平面的大小,但是输入的图片一般是一个RGB的三维张量,对于deepth这一个维度,如果为1的话,那么filter是(3,3),但是如果deepth大于1的话,这个filter的deepth维度一般是和张量中的deepth维度一样的。
deepth=1时,filter=(3,3),处理输入中33 个节点的值
deepth=2时,filter=(3,3),会处理输入中332个节点的值
deepth=n时,filter=(3,3),会处理输入中$33\times n$个节点的值

zero paddings

因为经过filter处理后,输入的矩阵维度会变小,所以,如果经过很多层filter处理后,就会变得越来越少,因此,为了解决这个问题,提出了zero paddings,zero padding是在filter要处理的输入上,在输入的最外层有选择的加上一行(列)或多行(列)0,从而保持输入经过filter处理之后形状不变。

feature map

一个filter的输出就是一个feature map,该feature map的width和height为:$(input_size + 2\times padding_size - filter_size)/stride + 1$
一个filter可以提取一个feature,得到一个feature map,为了提取多个feature,需要使用多个filters,最后可以得到多个feature map。

所以说,feature map是一类值,因为它对应的是一个filter,给定不同的输入images,一个feature map可以有不同的取值。这个问题是我在看ZFNet中遇到的,因为它在原文中说
“For a given feature map, we show the top 9 activations”。给定一个feature map,这里应该是在所有样本中选择最大的$9$个activations对应的images。
“the strongest activation (across all training examples) within a given feature map”。给定一个feature map,在所有样本中选择一个最强的activation。

activate function

一般使用非线性激活函数relu对feature map进行变化

pooling

maxpooling

它基本上采用一个filter和一个同样长度的stride通常是(2,2)和2,然后把它应用到输入中,输出filter卷积计算的每个区域中的最大数字,这个pooling是在各个维度上分别进行的。
比如一个 22422464的input,经过一个(2,2)的maxpooling会输出一个11211232的张量

averagepooling

fc layers

Alexnet(2012)

论文名称:ImageNet Classification with Deep Convolutional Neural Networks
论文地址:http://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf

概述

作者提出了一个卷积神经网络架构对Imagenet中$1000$类中的$120$万张图片进行分类。网络架构包含$5$个卷积层,$3$个全连接层,和一个$1000$-way的softmax层,整个网络共有$6000$万参数,$65000$个神经元。作者提出了一些方法提高性能和减少训练的时间,并且介绍了一些防止过拟合的技巧。最后在imagenet测试集上,跑出$37.5%$的top-1 error以及$17.0%$的top-5 error。
本文主要的contribution:

  1. 给出了一个benchmark-Imagenet
  2. 提出了一个CNN架构
  3. ReLU激活函数
  4. dropout的使用
  5. 数据增强,四个角落和中心的crop以及对应的horizontial 翻转。

问题

1.数据集太小,都是数以万计的,需要更大的数据集。

创新

ReLU非线性激活函数

作用

作者说实验表明ReLU可以加速训练过程。

saturating nonlinearity

一个饱和的激活函数会将输出挤压到一个区间内。

A saturating activation function squeezes the input.

定义
f是non-saturating 当且仅当$|lim_{z\rightarrow -\infty} f(z)| \rightarrow + \infty$或者$|lim_{z\rightarrow +\infty} f(z)| \rightarrow + \infty$
f是saturating 当且仅当f不是non-saturating
例子
ReLU就是non-saturating nonlinearity的激活函数,因为$f(x) = max(0, x)$,如下图所示。
relu
当$x$趋于无穷时,$f(x)$也趋于无穷。
sigmod和tanh是saturating nonlinearity激活函数,如下图所示。
sigmo
tanh

多块GPU并行

作者使用了两块GPU一块运行,每个GPU中的参数个数是一样的,在一些特定层中,两个GPU中的参数信息可以进行通信。

Overlapping Pooling

就是Pooling kernel的size要比stride大。比如一个$12\times 12$的图片,用$5\times 5$的pooling kernel,步长为$3$,步长要比kernel核小,即$3$比$5$小。
为什么这能减小过拟合?

  • 可能是减小了Pooling过程中信息的丢失。

If the pooling regions do not overlap, the pooling regions are disjointed and if that is the case, more information is lost in each pooling layer. If some overlap is allowed the pooling regions overlap with some degree and less spatial information is lost in each layer.[4]

数据增强

目的:防止过拟合

裁剪和翻转

输入是$256\times 256 \times 3$的图像。
训练:对每张图片都提取多个$224\times 224$大小的patch,这样子总共就多产生了$(256-224)\times (256-224) = 1024$个样本,然后对每个patch做一个水平翻转,就有$1024\times 2 = 2048$个样本。
测试:通过对每张图片裁剪五个(四个角落加中间)$224\times 224$的patches,并且对它们做翻转,也就是有$10$个patches,网络对十个patch的softmax层输出做平均作为预测结果。

在图片上调整RGB通道的密度

使用PCA对RGB值做主成分分析。对于每张训练图片,加上主成分,其大小正比于特征值乘上一个均值为$0$,方差为$0.1$的高斯分布产生的随机变量。对于一张图片$x,y$点处的像素值$I_{xy}=[I_{xy}^R, I_{xy}G,I_{xy}B]^T$,加上$[\bold{p_1},\bold{p_2},\bold{p_3}][\alpha_1\lambda_1,\alpha_2\lambda_2,\alpha_3\lambda_3]$,其中$[\bold{p_1},\bold{p_2},\bold{p_3}]$是特征向量,$\lambda_i$是特征值,$\alpha_i$就是前面说的随机变量。

Dropout

通过学习鲁棒的特征防止过拟合。
在训练的时候,每个隐藏单元的输出有$p$的概率被设置为$0$,在该次训练中,如果这个神经元的输出被设置为$0$,它就对loss函数没有贡献,反向传播也不会被更新。对于一层有$N$个神经单元的全连接层,总共有$2^N$种神经元的组合结果,这就相当于训练了一系列共享参数的模型。
在测试的时候,所有隐藏单元的输出都不丢弃,但是会乘上$p$的概率,相当于对一系列集成模型取平均。具体可见dropout
在该模型中,作者在三层全连接层的前两层输出上加了dropout。

局部响应归一化(Local Response Normalizaiton)

事实上,后来发现这个东西没啥用。但是这里还是给出一个公式。

$$ b^i_{x,y} = \frac{a^i_{x,y}}{(k+\alpha \sum{min(N-1,\frac{i+n}{2})}_{j=max(0,\frac{i-n}{2})}(aj_{x,y})^2)^{\beta}}$$
其中$a^i_{x,y}$是在点$(x,y)$处使用kernel $i$之后,在经过ReLU激活函数。$k,n,\alpha,\beta$是超参数。

It seems that these kinds of layers have a minimal impact and are not used any more. Basically, their role have been outplayed by other regularization techniques (such as dropout and batch normalization), better initializations and training methods.

整体架构

目标函数

多峰logistic回归。

并行框架

下图是并行的架构,分为两层,上面一层用一个GPU,下面一层用一个GPU,它们只在第三个卷积层有交互。
alexnet

简化框架

下图是简化版的结构,不需要使用两个GPU。
alexnet_simple

数据流(简化框架)

输入是$224\times 224 \times 3$的图片,第一层是$96$个stride为$4$的$11\times 11\times 3$卷积核构成的卷积层,输出经过max pooling(步长为2,kernel size为3)输入到第二层;第二层有$256$个$5\times 5\times 96$个卷积核,输出经过max pooling(步长为2,kernel size为3)输入到第三层;第三层到第四层,第四层到第五层之间没有经过pooling和normalization),第三层有384个$3\times 3\times 256$个卷积核,第四层有$384$个$3\times 3\times 384$个卷积核,第五层有$256$个$3\times 3\times 384$个卷积核。然后接了两个$2048$个神经元的全连接层和一个$1000$个神经元的全连接层。

实验

Datasets

ILSVRC-2010

Baselines

  • Sparse coding
  • SIFT+FV
  • CNN

Metric

  • top-1 error rate
  • top-5 error rate

代码

pytorch实现
https://github.com/mxxhcm/myown_code/blob/master/CNN/alexnet.py

Maxout networks

论文名称:Maxout Networks
下载地址:https://arxiv.org/pdf/1302.4389.pdf

NIN

论文名称:Network In Network
论文地址:https://arxiv.org/pdf/1312.4400.pdf

摘要

这篇文章作者使用更复杂的micro神经网络代替CNN,用一个mlp实例化micro nn。CNN中的filter用的是generalized linear model(GLM)。本文使用nonlinear的FA,作者用一个multi layers perceptron 取代GLM。通过和cnn类似的操作对input进行sliding得到feature maps,然后传入下一层,deep NIN通过堆叠多层类似的结构生成。同时作者使用average pooling取代最后的fullcy connected layer。
本文的两个contribution是:

  1. 使用MLP代替CNN中linear model,引入$1\times 1$的filter
  2. 使用average pooling代替fully connected layer。

在传统的CNN中,一个concept的不同variation可能需要多个filters,这样子会让下一层的的计算量太大。高层CNN的filters对应input的区域更大,高层的concept是通过对底层的concepts进行组合得到的。这里作者在每一层都对local patch进行组合,而不是在高层才开始进行组合,在每一层中,micro network计算更加local patches更abstract的特征。

Network in Network

MLP convolution layers

为什么使用MLP代替GLP?

  1. MLP和CNN的结构兼容,可以使用BP进行训练;
  2. MLP本身就是一个deep model,满足feature复用的想法。

如下图所示,是MLP CNN和GLP CNN的区别。
mvl_vs_glp

MLP的公式如下。
equ
从cross channel(feature maps)的pooling角度来看,上面的公式相当于在一个正常的conv layer上进行多次的parametric pooling,每一个pooling layer对输入的feature map进行线性加权,经过一个relu层之后在下一层继续进行pooling。Cross channel pooled的feature maps在接下来的层中多次进行cross channel pooling。这个cross channel pooling的结构的作用是学习复杂的cross channel信息。
其实整个cross channel的paramteric pooling结构相当于一个普通的卷积加上了多个$1\times 1$的卷积,如下图所示:
11filter

Global average pooling

FC layers证明是容易过拟合的,dropout被提出来正则化fc layers的参数。
本文提出的global average pooling取代了CNN的fc layers,直接在最后一个mlpconv layer中对应于分类任务中的每个类别生成一个feature map。然后用在feature maps上的average pooling代替fc layers,然后把它送入softmax layer。原来的CNN是将feature map reshape成一个一维向量,现在是对每一个feature map进行一个average pooling,有多少个feature map就有多少个pooling,相当于一个feature map对应与一个类型。
这样做有以下几个好处:

  1. 在fc layers上的global average pooling让feature map和categories对应起来,feature map可以看成类别的置信度。
  2. 直接进行average pooling不用优化fc layer的参数,也就没有过拟合问题。
  3. global average pooling对全局信息进行了加和,对于input的spatial信息更加鲁邦。

NIN

如下图所示,是NIN的整体架构。
nin
下图是一个具体参数化的示例
instance

实验

OverFeat(2013)

论文名称:OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks
论文地址:https://arxiv.org/pdf/1312.6229.pdf

概述

本文提出了一个可用于classification, localization和detection等任务的CNN框架。
ImageNet数据集中大部分选择的是几乎填满了整个image中心的object,image中我们感兴趣的objects的大小和位置也可能变化很大。为了解决这个问题,作者提出了三个方法:

  1. 用sliding window和multiple scales在image的多个位置apply ConvNet。即使这样,许多window中可能包含能够完美识别object类型的一部分,比如一个狗头。。。最后的结果是classfication很好,但是localization和detection结果很差。
  2. 训练一个网络不仅仅预测每一个window的category distribution,还预测包含object的bounding box相对于window的位置和大小。
  3. 在每个位置和大小累加每个category的evidence

Vision任务

classification,localization和detection。classification和localization通常只有一个很大的object,而detection需要找到很多很小的objects。
classification任务中,每个image都有一个label对应image中主要的object的类型。为了找到正确的label,每个图片可以猜$5$次(图片中可能包含了没有label的数据)。localization任务中,不仅要给出label,还需要找到这个label对应的bouding box,bounding box和groundtruth至少要有$50$匹配,label和bounding box也需要匹配。detection和localization不同的是,detection任务中可以有任何数量的objects,false positive会使用mean average precison measure。localization任务可以看成classification到detection任务的一个中间步。

FCN

用卷积层代替全连接层。具体是什么意思呢。
alexnet中,有5层卷积层,3层全连接层。假设第五层的输出是$5\times 5 \times 512$,$512$是output channels number,$5\times 5$是第五层的feature maps的大小。如果使用全连接的话,假设第六层的输出单元是$N$个,第六层权重总共是$(5\times 5\times 512) * (N)$,对于一个训练好的网络,图片的输入大小是固定的,因为第六层是一个全连接层,输入的大小是需要固定的。如果输入一个其他大小的图片,网络就会出错,所以就有了Fully Convolutional networks,它可以处理不同大小的输入图片。
如下所示,使用某个大小的image训练的网络,在classifier处用卷积层替换全连接层,如果使用全连接层,首先将$(5, 5, out_channels)$的feature map进行flatten $5\times 5\times out_channels$,然后经过三层全连接,最后输出一个softmax的结果。而fcn使用卷积层代替全连接,使用$N$个$5\times 5$的卷积核,直接得到$1\tims 1 \times N$的结果,最后得到一个$1\times 1\times C$的输出,$C$代表图像类别,$N$代表全连接层中隐藏节点的数量。
fcn
事实上,FCN和全连接的本质上都是一样的,只不过一个进行了flatten,一个直接对feature map进行操作,直接对feature map操作可以处理不同大小的输入,而flatten不行。
当输入图片大小发生变化时,输出大小也会改变,但是网络并不会出错,如下所示:
fcn2
最后输出的结果是$2\times 2 \times C$的结果,可以直接对它们取平均,最后得到一个$1\times 1\times C$的分类结果。

offset Max pooling

我们之前做max pooling的时候,设$kernel_size=3, stride_size=1$,如果feature map是$3$的倍数,那么只有一个pooling的结果,但是如果不是$3$的倍数,max pooling会很多个结果,比如有个$20\times 20$的feature map,在$x,y$上做max pooling分别有三种结果,分别从$x,y$的位置$0$开始,位置$1$开始,位置$2$开始,排列组合有$9$中情况,这九种情况的结果是不同的。
如下图所示,在一维的长为$20$的pixels上做maxpooling,有三种情况。
offset_maxpooling

overfeat

这两个方法中,fcn是在输入图片上进行的window sliding,而offset maxpooling是在feature map进行的window sliding,这两个方法结合起来就是overfeat,要比alexnet直接在输入图片上进行window sliding 要好。

Classification

training

  • datset
    Image 2012 trainign set(1.2million iamges,C=$1000$ classes)。
  • data argumented
    对每张图片进行下采样,所以每个图片最小的dimension需要是$256$。
    提取$5$个random crops以及horizaontal flips,总共$10$个$221\times 221$的图片
  • batchsize
    $128$
  • 初始权重
    $(\mu, \sigma)= (0, 1\times 10^{-2})$
  • momentum
    0.6
  • l2 weigth decay
    $1\times 10^{-5}$
  • lr
    初始是$5\times 10^{-2}$,在$(30,50,60,70,80)$个epoches后,乘以$0.5$
  • non-spatial
    这个说的是什么呢,在test的时候,会输出多个output maps,对他们的结果做平均,而在training的时候,output maps是$1\times 1$。

model架构

下图展示的是fast model,spatial input size在train和test时候是不同的,这里展示的是train时的spatial seize。layer 5是最上层的CNN,receptive filed最大。后续是FC layers,在test时候使用了sliding window。在spatial设置中,FC-layers替换成了$1\times 1$的卷积。
overfeat_fast
下图给出了accuracy model的结构,
overfeat_accuracy
总的来说,这两个模型都在alexnet上做了一些修改,但是整体架构没有大的创新。

多scale classification

alexnet中,对一张照片的$10$个views(中间,四个角和horizontal flip)的结果做了平均,这种方式可能会忽略很多趋于,同时如果不同的views有重叠的话,计算很redundant。此外,alexnet中只使用了一个scale。
作者对每个iamge的每一个location和多个scale都进行计算。
如下图,对应了不同大小的输入图片,layer 5 post pool中$(m\times n)\time(3\times 3)$,前面$m\times n$是fcn得到的不同位置的feature map,后面$3\times 3$是$kernel_size=3$的offset max pooling得到的featrue map。乘起来是所有的预测结果。
multi_scale

localization

Detection

ZFNet(2014)

论文名称:Visualizing and Understanding Convolutional Networks
论文地址:https://cs.nyu.edu/~fergus/papers/zeilerECCV2014.pdf
为什么叫ZFNet,两个作者名字首字母的拼写。

首先我有一个问题?就是什么是一个activation。在原文的$2.1$节,有这样一个介绍:

We present a novel way to map these activities back to the input pixel space, showing what input pattern originally caused a given activation in the feature maps.
我的理解是一个activation就是feature map中的一个unit。事实上,feature map也叫activation map,因为它是image中不同parts的acttivation,而叫feature map是因为它是image中找到特定的feature。

概述

这篇文章从可视化的角度给出中间特征的和classifier的特点,分析如何改进alexnet来提高imagenet classification的accuracy。
为什么CNN结果这么好?

  1. training set越来越大
  2. GPU的性能越来越好
  3. Dropout等正则化技术

但是CNN还是一个黑盒子,我们不知道它为什么表现这么好?这篇文章给出了一个可视化方法可视化任意层的feature。

那么本文的contribution是什么呢?使用deconvnet进行可视化,通过分析特征行为,对alexnet进行fine tune提升模型性能。

使用deconvnet可视化

什么是deconvnet?可以看成和convnet拥有同样组成部分(pooling, filter)等,但是是反过来进行的。如下图所示,convnet是把pixels映射到feature,或者到底层features映射到高层features,而deconvnet是把高层features映射到底层features,或者把features映射到pixels。在测试convnet中给定feature maps的一个activation时,设置所有其他的activation为0,将这个feature map传入deconvnet网络中。
fig1
图片左上为deconv,右上为conv。conv的流程为filter->rectify->pooling;deconv的流程为unpool->rectify->filter。

Unpooling

convnet中的max pooling是不可逆的,这里作者使用switch variables记录下max pooling后的元素在没有pooling时的位置,进行近似的恢复。

Rectification

convnet使用relu non-linearities。deconvnet还是使用relu,这里我有些不理解,为什么?为什么deconve还是使用relu

Filtering

deconvnet使用convnet中filters的transposed版本。

Training

整体架构

fig3.png

  • training set
    1.3百万张图片,1000类
  • processed
    每个RGB图像resized成最小边维度为$256$,cropping中间的$256 \times 256$,减去所有像素的平均值。crops$10$个$224\times 224$(四个角落和中心以及horizontal flips)
  • 优化方法
    带momentumSGD
  • batch size
    128
  • lr
    初始是$10^{-2}$,然后手动anneal
  • momentum
    0;9
  • Dropout
    layer 6和layer 7,0.5
  • weights和biases初始化
    weights设置为$10^{-2}$,biases设置为$0$
  • normalizaiton
    对第一层的filter,如果RMS超过了$10^{-1}$就设置为$10^{-1}$
  • 训练次数
    70epochs

Visualizaiton

Feature visualization

如下图所示,使用deconvnet可视化一些feacutre activation。给定一个feature map,选择其中最大的$9$个activations对应的样本,一个feature map是通过一个filter得到的,而一个filter提取的是一个特征,所以这$9$个activations都是一个filter提取的不同图片中的同一个特征。然后将它们输入deconvnet,得到pixel spaces,可以查看哪些不同的结构(哪些原始)产生了这个feature,展现这个filter对于输入deformation的invariance。在黑白图像的旁边有对应的图像原图,他们要比feature的variation更多,因为feature关注的是图像的invariance。比如layer 5的第一行第二列的九个图,这几个patch看起来差异很大,但是却在同一个feature map中,因为这个feature map关注的是背景中的草,并不是其他objects。更多的我们可以看出来,第二层对应corner和edge等,第三次对应更复杂的invariances,比如textures和text等。第四层更class-specific,第五层是object variation。
fig2

Feature evolution durign training

下图随机选择了几个不同的feature,然后展示了他们在不同layer不同epochs(1, 2, 5, 10, 20, 30, 40, 64)的可视化结果。
fig4

架构选择

通过可视化alexnet的first layer和second layer,有了各种各样的问题。First layer中主要是high和low frequency的信息,而2nd layer有很多重复的,因为使用stride为$4$而不是$2$。作者做了两个改进:

  1. 将first layer的filter size从$11\times 11$改成了$7\times 7$
  2. 卷积的步长从$4$改成了$2$

如下图所示:
fig5

Occlusion Sensitivity

model是否真的识别了object在image中的位置,还是仅仅使用了上下文信息?下图中的例子证明了model真的locate了object,当遮挡住物体的部分增大时,给出正确分类的概率就减小了。移动遮挡方块的位置,给出一个和方块位置相关的分类概率函数,我们可以看出来,model really works。
fig6

实验

第一个实验通过使用,证明了前面的特征提取层和fc layers都是有用的。
第二个实验保留前面的特征提取层和fc layers,将最后的softmax替换。

VGGNet(2014)

论文名称:VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION
论文地址:https://arxiv.org/pdf/1409.1556.pdf http://arxiv.org/abs/1409.1556.pdf
VGG是Visual Geometry Group的缩写

概述

这篇文章主要研究了CNN深度对大规模图像识别问题精度的影响。本文的主要contribution就是使用多层的$3\times 3$ filters替换大的filter,增加网络深度,提高识别精度。

方案

架构

训练,输入$224\times 224$大小的RGB图片。对每张图片减去训练集上所有图片RGB 像素的均值。预处理后的图片被输入多层CNN中,CNN的filter是$3\times 3$的,作何也试了$1\times 1$的filter,相当于对输入做了一个线性变换,紧跟着一个non-linear 激活函数,这里的$1\times 1$的filter没有用于dimention reduction。stride设为$1$,添加padding使得卷积后的输出大小不变。同时使用了$5$个max-pooling层(并不是每一层cnn后面都有max-pooling),max-pooling的window是$2\times 2$,stride是$2$。
在训练的时候CNN后面接的是三个FC layers,前两个是$4096$单元,最后一层是$1000$个单元的softmax。所有隐藏层都使用ReLu非线性激活函数。
在测试的时候使用fcn而不是直接flatten。

配置

这篇文章给出了五个网络架构,用$A-E$表示,它们只有在深度上有所不同:从$11$层($8$个conv layers和$3$个FC layers)到$19$层($16$个conv layers和$3$个FC layers)。Conv layers的channels很小,从第一层的$64$,每过一个max pooling layers,变成原理啊的两倍,直到$512$。具体如下表所示。
vgg_conf
网络的参数个数如下表所示。
vgg_weights_num
网络$A$的参数计算:
\begin{align*}
64\times 3\times 3\times 3 + \\
128\times 3\times 3\times 64 + \\
256\times 3\times 3\times 128 + \\
256\times 3\times 3\times 256 + \\
512\times 3\times 3\times 256 + \\
512\times 3\times 3\times 512 + \\
2\times 512\times 3\times 3\times 512 + \\
7\times 7\times 512\times 4096 + \\
4096\times 4096 + \\
4096\times 1000 = \\
132851392
\end{align*}
网络$B$的参数计算:
\begin{align*}
64\times 3\times 3\times 3 + \\
128\times 3\times 3\times 64 + \\
128\times 3\times 3\times 128 + \\
256\times 3\times 3\times 128 + \\
256\times 3\times 3\times 256 + \\
256\times 3\times 3\times 256 + \\
512\times 3\times 3\times 256 + \\
512\times 3\times 3\times 512 + \\
2\times 512\times 3\times 3\times 512 + \\
7\times 7\times 512\times 4096 + \\
4096\times 4096 + \\
4096\times 1000 = \\
133588672
\end{align*}
其实主要的网络参数还是在全连接层,$7\times 7\times 512\times 4096=102760448
$。

卷积核作用

  1. 为什么要用三个$3\times 3$的conv layers替换$7\times 7$个conv layers?
  • 使用三个激活函数而不是一个,让整个决策更discriminative。
  • 减少了网络参数,三个有$C$个通道的$3\times 3$conv layers,总的参数是$3\tims(32C2)=27C^2$,而一个$C$通道的$7\times 7$ conv layers,总参数是$49C^2$。可以看成是一种正则化。
  1. $1\times 1$ conv layers用来增加非线性程度,本文中使用的$1\times 1$的conv layers可以看成加了非线性激活函数的投影。

分类框架

training

  • 目标函数
    多峰logistic regression
  • 训练方法
    mini-batch gradient descent with momentum
  • batch size
    256
  • momentum
    0.9
  • 正则化
    $L_2$参数正则化(5\codt 10^{-4})
    0.5 dorpout 用于前两个FC layers
  • lr
    初始值为$10^{-2}$,当验证集的accuracy不再提升时,除以$10$。学习率总共降了$3$次,$370K$次迭代后停止。
  • 图像预处理
    从rescaled中随机cropped $224\times 224$的RGB图像。
    使用alexnet中的随机horizontal flipping和随机RGB colour shift。
  • iamge rescale
    用$S$表示training image的小边的大小,$S$也叫作train sacle。网络的输入是从training image中cropped得到的$224\times 224$的图像。所以只要$S$取任何不小于$224$的值即可,如果$S=224$,那么crop在统计上会captuer整个图片,完全包含training image最小的那边;$S>>224$的时候,crop会产生很小一部分的图像。
    作者尝试了固定$S$和不固定的$S$。对于固定$S$,设置$S=256$和$S=384$,首先在$S=256$上训练,然后用$S=256$训练的参数初始化$S=384$的参数,使用更小的初始学习率$10^{-3}$。不固定$S$时,$S$从$[S_{min}, S_{max}](S_{max}=512,S_{min}=256)$任意采样,然后crop。
  • VGG vs alexnet
    VGG参数多,深度深,但是收敛快,原因:
  1. 更小的filter带来的implicit regularisation
  2. 某些层的预先初始化。
    这个解决的是网络深度过深,某些初值使得网络不稳定的问题。解决方法:先随机初始化不是很深的网络A,进行训练。在训练更深网络的时候,使用A网络的值初始化前$4$个卷基层和最后三个FC layers。随机初始化的网络参数,从均值为$0$,方差为$10^{-2}$的高斯分布中采样得到。

testing

  1. 测试的时候先把input image的窄边缩放到$Q$,$Q$也叫test scale,$Q$和$S$不一定需要相等。
  2. 这里和overfeat模型一样,在卷积网络之后采用了fcn,而不是fc layers。

classfication

ILSVRC-2012,training($1.3M$张图片),validation($50K张$),testing($100K$张)
两个metrics:top-1和top-5 error。top-1 error是multi-class classification error,不正确分类图像占的比例;top-5 error是预测的top-5都不是ground-truth。

single scale evaluation

$S$固定时,设置test image size $Q=S=256$;
$S$抖动时,设置test image size $Q=0.5(S_{min}+S_{max})=0.5(256+512)=384$,$S\in [S_{min},S_{max}]$。

multi scale evaluation

用同一个模型对不同rescaled大小的图片多次test,即对于不同的$Q$。
固定$S$时,在三个不同大小的test image size $Q={S-32,S,S+32}$评估。
$S$抖动时,模型是在$S\in [S_{min},S_{max}]$上训练的,在$Q={S_{min}, 0.5(S_{min}+S_{max}), S_{max}}$上进行test。

多个crop evaluation

这个是为了和alexnet做对比,alexnet网络在testing时,对每一张图片都进行多次cropped,对testing的结果做平均。

convnet funsion

之前作者的evaluation都是在单个的网络上进行的,作者还试了将不同网络的softmax输出做了平均。

Inception V1(GoogleLeNet)

摘要

提出一种方法能够在不增加太多计算代价的同时增加网络的深度和宽度。

motivation

直接增加网络的深度和宽度有两个缺点:

  1. 参数更多,容易过拟合,尤其是训练集太小的情况下,高质量的训练集很难生成。
  2. 需要更多的计算资源。比如两层CNN,即使每一层中线性增加filters的个数也会造成计算代价指数级增加。如果增加的权重接近$0$的话,计算代价就浪费了。而现实中的计算资源是有限的。

如何解决这个问题呢?使用sparsity layers取代fully connetcted layers。但是现在的计算资源在处理non-uniform 的sparse data时是非常低效的,即使数值操作减小$100$倍,查找的时间也是很多的。而针对CPU和GPU的dense matrix计算能够加快fc layer的学习。现在绝大部分的机器学习视觉模型在sparsity spatial domain都仅仅利用了CNN,而convolution是和前一层patches的dense connection。1998年的convnet为了打破网络对称性,改善学习结果,使用的是random和sparse连接,而在alexnet中为了并行优化计算,使用了全连接。当前cv的state-of-the-art架构使用的都是unifrom structure,为了高效的进行dense计算,filters和batch size的数量都是很大的。
稀疏性可以解决过拟合和资源消耗过多的问题,而稠密连接可以提高计算效率。所以接下来要做的是一个折中,利用filter维度的稀疏结构,同时利用硬件在dense matrices上的计算进行加速。
Inception架构就是使用一个dense组件去逼近sparse结构的例子。

算法

Inception的idea是使用dense组件近似卷积的局部稀疏结构。本文的旋转不变型是利用convolutional building blocks完成的,找到optimal local construction,然后不断堆叠。文章[11]中建议layer-by-layer的构建,分析上一层之间的关系,并将具有高相关性的units进行分组。这些相关的units cluster构建成了下一层的units,并且和上一层的units相连接。假设之前层中的每一个unit都对应输入图片中的一些region,这些units分组构成filter banks。这就意味着在靠近输入的层中我们会得到很多关于local regions相关的units。通过在下一层中使用$1\times 1$的卷积,可以找到关注于同一个region的很多个clusters。(这里加一些我自己的理解,$1\times 1$的卷积层可以找到那些重复的feature map??)当然,也有可能有更大的cluster可以通过在更大的patches上进行卷积得到,所以这里同时在一层中同时使用$1\times 1, 3\times 3, 5\times 5$的filters,使用这些大小的filter仅仅是因为方便,然后将他们的输出进行组合当做下一层的输入。当然可以加上pooling,如下图所示。
naive inception
但是,这样子计算量还是很大,大量$3 \times 3, 5\times 5$在卷积时的计算量,如果再加上输入shape和输出shape相等的max pooling操作,下一层的输入维度相当大,计算开销j就爆炸了。这就使用了本文的第二个idea:使用$1\times 1$的filter降维减少计算量。在$3\times 3, 5\times 5$大小filter之前添加$1\times 1$的卷积进行降维。
dimension reduction inception

这个架构的好处:

  1. 在每一层都可以增加units的数量而不用担心计算量暴增。首先将上一层大量filters的输出进行进行降维,然后输入到下一层。
  2. visual信息用不同的scales进行处理,然后拼接起来,这样子在下一层可以同时从不同scales中提出features。

GoogLeNet

作者给出了Inception的一个示例,叫GoogLeNet。网络具体配置如下:
GoogLeNet
其中,"#$3 \times 3$ reduce"和"#$5 \times 5$ reduce"表示在$3\times 3, 5\times 5$卷积之前使用$1\times 1$的filters个数,pool proj这一列表示在max pooling之后的$1\times 1$的filters个数。
作者在GoogLeNet中还使用了两个额外的分类层辅助训练。通过观察得知相对shallower的网络有很好的性能,那么在反向传播时,深层网络的中间特征应该是很有判别力的。
通过在网络中间添加辅助的classfiers,作者想要让网络底层也有判别力。在训练的时候,在$4a$和$4d$模块后添加分类器,然后将所有的loss乘上一个权重加到总的loss上,在test时,这些辅助网络被扔掉。

Batch Normalization

论文名称:Batch Normalization: Accelerating Deep Network Training b
y Reducing Internal Covariate Shift
论文地址:https://arxiv.org/pdf/1502.03167.pdf

概述

在训练深度神经网络的时候,随着训练的不断进行,网络权重在不停的变,除了第一层之外的每层输入也在不停的变,所以就使得权重每次都要去适应新的输入distributions。这就导致训练速度很慢,学习率的要很小,很难使用saturaing nonlinearities激活函数训练。作者把这个问题叫做internal covariate shift,提出了batch normalization解决该问题,bn对于参数初始化的要求没那么高,允许使用更高的学习率。
BN可以看成一种正则化手段。

简介

SGD相对于单个样本的GD来说,使用mini-batch的梯度作为整个训练集的估计值,效果更好;同时并行计算提高了效率。之前的工作使用ReLU,更好的初始化以及小的学习率来解决梯度消失问题,而本文作者的想法是让非线性输入的分布尽可能稳定,从而解决梯度饱和等问题,加快训练。本文提出的batch normalization通过固定每一层输入的均值和方差减少internal covariate shift,同时减少了gradients对于初始参数的依赖性。在使用了BN的网络中,也可以使用如sigmod和tanh的saturating nonlirearities激活函数,并不是一定要用relu激活函数。

Mini-Batch Normalization

Whitening每一层的所有inputs需要很大的代价,而且并不是每个地方都是可导的。作者进行了两个简化。第一个是并不是对所有输入的features进行whiten,而是对每一个feautre单独的normalization,将他们转化成均值为0,方差为1的数据。对于一个d维的输入$x=(x^1,\cdots, x^d),对每一维进行normalize:
$$\hat{x}^k= \frac{x^k - \mathbb{E}\left[xk\right]}{\sqrt{Var\left[xk\right]}}$$
其中的期望和方差是整个training set 的期望和方差。但是仅仅normalize每一层的输入可能改变这一层的表示。比如normalize sigmod的输入会将它们的输出限制在非线性的线性区域。为了解决这个问题,在网络中添加的这个transformation应该能够表示identity transform,作者对每个activation $xk$引入了一对参数,$\gammak, \beta^k$,它们对normalized value进行scale和shift:
$$y^k = \gamma^k \hat{x}^k + \beta^k$$
这些参数和模型参数一块,都是学习出来的,如果学习到$\gammak=\sqrt{Var\left[xk\right]},\beta^k = \mathbb{E}\left[x^k\right]$,就可以表示恒等变换了。。
上面说的是使用整个training set的方差和期望进行normaliza,事实上,在sgd中这是不切合实际的。因此,就引入了第二个简化,使用每个mini-batch的方差和期望进行normalize,并且方差和期望是针对于每一个维度计算的。给出一个大小为$m$的batch $B$,normalization独立的应用于每一个维度。用$\hat{x}_{1,\cdots, m}$表示normalized values,以及它们的linear transformation:$y_{1,\cdots,m}$。这个transform表示为:$BN_{\gamma, \beta}:x_{1,\cdots, m} \rightarrow y_{1,\cdots,m}$,称为Batch Normalization Transform,完整的算法如下:
算法1 Batch Normalizing Transform
输入: mini-batch:$B={x_{1,\cdots, m}},要学习的参数$\gamma,\beta$
输出:${y_i=BN_{\gamma,\beta}(x_i)}$
$\mu\leftarrow \frac{1}{m}\sum_{i=1}^mx_i$ 计算batch的mean
$\sigma^2_B\leftarrow \sum_{i=1}m(x_i-\mu_B)2$ 计算batch的variance
$\hat{x}_i\leftarrow \frac{x_i-\mu_B}{\sqrt{\simga^2_B+\epsilon}}$ normalize
$y_i\leftarrow \gamma \hat{x}_i+ \beta \equiv BN_{\gamma, \beta}(x_i)$ scale以及shift。
整个过程的loss还可以通过backpropagate进行传播,即它是可导的。

Batch-Normalized CNN

原来的CNN是
$$ z= g(Wu+b)$$
现在在nonlinearity前加上BN transform。
$$ z= g(BN(Wu+b))$$
但是事实上,Wu+b和Wu的效果是一样的,因为normalized的时候会减去均值,所以最后就是:
$$ z= g(BN(Wu))$$
BN在Wu的每一个维度上单独使用BN,每一个维度有一对$\gammak,\betak$。

BN能使用更大的学习率

BN正则化模型

Residual Network(2015)

论文名称:Deep Residual Learning for Image Recognition
论文地址:https://arxiv.org/pdf/1512.03385.pdf

概述

作者提出了参差网络,容易优化,仅仅增加深度就能得到更高的accuracy。在Imagenet上使用比VGG深八倍的152层的residual网络,但是计算复杂度更低。
网络是不是越深越好?并不是!事实上,随着网络的加深,会出现退化问题-即增加网络的深度,accuracy反而会下降。导致这个问题的原因并不是过拟合,至于是什么原因?
在这篇文章中,作者提出了deep residual network。使用一些stacked non-linear layers你和一个residual mapping,而不是直接学习一个underlying mapping。用$H(x)$表示一个underlying mapping,我们的目标是学习一个residual mapping:$F(x) = H(x)-x$,underlying mapping可以写成$H(x) = F(x)+x$。在某种情况下,如果identity mapping是optimal,那么让$F(x)$接近于$0$可能比让stacked non linear layers拟合一个identity mapping要简单。。如下图所示,$H(x)$可以用下图表示,由一个feedforward nn加上shortcut connections(skip one or more layers的connection)组成:
residual block
shortcut connection在这里就是一个identity mapping,不需要额外的参数和计算量,shorcut的输出和$F(x)$的输出再一块经过relu激活函数。

本文的contribution是什么?
加了一个恒等映射让深度网络的训练变得更容易。具体原理是什么?可以从这样一个角度看,在每一层都可以把不同维度的feature进行重组。residual connection是skip的一种方式??

Residual Learning

用$H(x)$表示stacked non linear layers拟合的一个underlying mapping,$x$为stacked layers的输入。原来我们用这些layers逼近一个复杂的函数,现在我们用它逼近residual function,即$F(x) = H(x) -x$(假设输入和输出的维度是一样的),原来想要拟合的函数变成了$F(x)+x$,它们的意义是一样的,但是对于learning的帮助却有很大差别。
如网络degradation问题中,如果更深的网络中添加的新layers是identity mapping,那么这个更深的网络的training error至少也要和浅一些的网络一样,然而事实上并不是这样的。在degradation问题中,说明multip nonlinear layers在近似identity mappings时效果并不是很好。而在residual learnign中,如果identity mapping是optimal,那么可以让non linear layers的权重接近于0,最后得到一个indetity mappings。虽然在real cases中,identity mapping几乎不可能是optimal的,但是如果optimal function更接近identity mapping而不是zero ampping,residual learning的效果就要更好。
residual block

Identity Mapping by Shortcuts

本文中采用的residual block如上上图所示,用公式表示为:
$$y = F(x, {W_i}) + x$$
其中$x,y$是输入和输出向量,函数$F(x, {W_i})$表示要学习的residual mapping,residual block块中有两层,$F=W_2\sigma(W_1x)$表示第一层和第二层,然后$F+x$表示shortcut connection以及element-wise addition。如果$x$和$F(x)$的维度不一样的话,可以进行一个linear projection:
$$y=F(x,{W_i}) + W_sx$$
$W_s$表示线性变换的矩阵。如果必要的话,$W_s$可以走一样线性变换,事实上,实验表明如果维度一样的话,identity mapping足够解决degradation问题,$W_s$就是用来进行dimension matting。
$F$的形式是很灵活的,可以像本文一样使用linear layers,当然也可以使用更多layers,无所谓。

网络架构

作者给出了三个网络架构,一个是VGG,一个是VGG修改得到的网络,另一个是这个修改的网络加上shortcut connection,如图所示。基于VGG的修改有以下两个原则:

  1. feature map的大小不变的话,filters的数量不变
  2. feature map的大小减半的话,filters的数量变为原来的$2$倍,保证每一层的计算复杂度不变。

网络最后接一个global average pooling layer和一个1000way的fc layer和softmax。

其他细节

  1. image的短边被resize到$[256, 480]$之间。然后从中裁剪一个$224 \times 224$的样本或者它的horizontal filp。
  2. 使用标准的颜色增强。
  3. 使用BN
  4. 从头开始训练网络
  5. 使用batch size为$256$的SGD
  6. 学习率从$0.1$开始,每到error不再改变时,除以$10$,总共进行$60\times 10^4$次迭代。
  7. 权重decay为$0.0001$,mementum为$0.9$。
  8. 测试时,对十个crop取平均,使用fcn,对多个scales上的scores进行平均。

结论

14.https://www.quora.com/How-does-deep-residual-learning-work
15.https://kharshit.github.io/blog/2018/09/07/skip-connections-and-residual-blocks
16.https://stats.stackexchange.com/questions/56950/neural-network-with-skip-layer-connections

python 常见问题(不定期更新)

发表于 2019-03-13 | 更新于 2019-12-17 | 分类于 python

问题1-‘dict_values’ object does not support indexing’

参考文献[1,2,3]

报错

1
'dict_values' object does not support indexing'

原因

The objects returned by dict.keys(), dict.values() and dict.items() are view objects. They provide a dynamic view on the dictionary’s entries, which means that when the dictionary changes, the view reflects these changes.
python3 中调用字典对象的一些函数,返回值是view objects。如果要转换为list的话,需要使用list()强制转换。
而python2的返回值直接就是list。

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
m_dict = {'a': 10, 'b': 20}
values = m_dict.values()
print(type(values))
print(values)
print("\n")

items = m_dict.items()
print(type(items))
print(items)
print("\n")

keys = m_dict.keys()
print(type(keys))
print(keys)
print("\n")

如果使用python3执行以上代码,输出结果如下所示:

class 'dict_values’
dict_values([10, 20])
class 'dict_items’
dict_items([(‘a’, 10), (‘b’, 20)])
class 'dict_keys’
dict_keys([‘a’, ‘b’])

如果使用python2执行以上代码,输出结果如下所示:

type ‘list’
[10, 20]
type ‘list’
[(‘a’, 10), (‘b’, 20)]
type ‘list’
[‘a’, ‘b’]

问题2-‘TimeLimit’ object has no attribute ‘ale’

参考文献[4,5,6]

问题描述

运行github clone 下来的DQN-tensorflow,报错:

AttributeError: ‘TimeLimit’ object has no attribute ‘ale’.

原因

是因为gym版本原因,在gym 0.7版本中,可以使用env.ale.lives()访问ale属性,但是0.8版本以及以上,就没有了该属性,可以在系列函数中添加如下修改:

1
2
3
4
5
6
7
8
9
10
11
def __init__(self, config):
self.step_info = None

def _step(self, action):
self._screen, self.reward, self.terminal, self.step_info = self.env.step(action)

def lives(self):
if self.step_info is None:
return 0
else:
return self.step_info['ale.lives']

ale属性是什么

我看官方文档也没有看清楚,但是我觉得就是生命值是否没有了

info (dict): diagnostic information useful for debugging. It can sometimes be useful for learning (for example, it might contain the raw probabilities behind the environment’s last state change). However, official evaluations of your agent are not allowed to use this for learning.

1
2
3
4
5
6
7
8
9
10
11
12
13
import gym
env = gym.make('CartPole-v0')
for i_episode in range(20):
observation = env.reset()
for t in range(100):
env.render()
print(observation)
action = env.action_space.sample()
observation, reward, done, info = env.step(action)
if done:
print("Episode finished after {} timesteps".format(t+1))
break
env.close()

问题3-cannot import name ***

参考文献[7]

报错

1
cannot import name tqdm

问题原因

谷歌了半天,没有发现原因,然后百度了一下,发现了原因,看来还是自己太菜了。。
因为自己起的文件名就叫tqdm,然后就和库中的tqdm冲突了,这也太蠢了吧。。。

问题4-linux下python执行shell脚本输出重定向

详细介绍

问题4-ImportError: No module named conda.cli’

问题描述

anaconda的python版本是3.7,执行了conda install python=3.6之后,运行conda命令出错。报错如下:

1
2
from conda.cli import main 
ModuleNotFoundError: No module named 'conda'

解决方案

找到anaconda安装包,加一个-u参数,如下所示。重新安装anaconda自带的package,自己安装的包不会丢失。
~$:sh xxx.sh -u

问题5-python-pip使用国内源

暂时使用国内pip源

使用清华源
~$:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple package-name
使用阿里源
~$:pip install -i https://mirrors.aliyun.com/pypi/simple package-name

将国内pip源设为默认

~$:pip install pip -U
~$:pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
~$:pip config set global.timeout 60

Writing to /home/username/.config/pip/pip.conf

查看pip配置文件

~$:find / -name pip.conf
我的是在/home/username/.config/pip/pip.conf

问题6-ImportError: /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.28 not found

问题描述

安装roboschool之后,出现ImportError。报错如下

1
ImportError: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /usr/local/lib/python3.6/dist-packages/roboschool/.libs/libQt5Core.so.5)

解决方案

在roboschool上找到一个issue,说从1.0.49版本退回到1.0.48即可。我退回之后,又出现以下错误:

1
ImportError: libpcre16.so.3: cannot open shared object file: No such file or directory

安装相应的库即可。完整的命令如下

1
2
~$:pip install roboschool==1.0.48
~$:sudo apt install libpcre3-dev

参考文献

1.https://www.cnblogs.com/timxgb/p/8905290.html
2.https://docs.python.org/3/library/stdtypes.html#dictionary-view-objects
3.https://stackoverflow.com/questions/43663206/typeerror-unsupported-operand-types-for-dict-values-and-int
4.https://github.com/devsisters/DQN-tensorflow/issues/29
5.https://gym.openai.com/docs
6.https://github.com/openai/baselines/issues/42
7.https://blog.csdn.net/m0_37561765/article/details/78714603
8.https://blog.csdn.net/u014432608/article/details/79066813
9.https://mirrors.tuna.tsinghua.edu.cn/help/pypi/

markdown帮助

发表于 2019-03-09 | 更新于 2019-12-17 | 分类于 工具

引用

代码引用

1
import tensorflow as tf

文字引用

实际是人类进步的阶梯。 --高尔基

表格

name age gender
Alice 11 female
Bob 82 male

表情

安装过程

第一步,卸载hexo默认的hexo-renderer-marked markdown渲染器
~$:npm un hexo-renderer-marked --save
第二步,安装支持emoji的markdown渲染器
~$:npm i hexo-renderer-markdown-it --save
第三步,修改博客根目录下的_config.yml文件,添加下列内容:

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
# Markdown-it config
## Docs: https://github.com/celsomiranda/hexo-renderer-markdown-it/wiki
markdown:
render:
html: true
xhtmlOut: false
breaks: true
linkify: true
typographer: true
quotes: '“”‘’'
plugins:
- markdown-it-abbr
- markdown-it-footnote
- markdown-it-ins
- markdown-it-sub
- markdown-it-sup
- markdown-it-emoji ## add emoji
anchors:
level: 2
collisionSuffix: 'v'
# If `true`, creates an anchor tag with a permalink besides the heading.
permalink: false
permalinkClass: header-anchor
# The symbol used to make the permalink
permalinkSymbol: ¶

然后重新生成部署即可。
测试:
😄
😆
👃

测试

Coding
Content
描述性提炼性质的研究
第一部分:
文献综述
(对话)
SPL
本文的文献综述贯穿在行文的过程中
(1)关于分家的原因:
敌军:①弗里德曼兄弟之间的利害冲突②许烺光夫妻纽带强于父子之间的纽带→概括为家庭内摩擦
作者(部分认同敌军基础上提出自己的观点):分家逐渐演化成一种“文化现象”
(2)分家中的“继”与“合”
敌军:①孔迈隆以家产正式分才算分家的定义②分灶
评论:①经济上的考虑多于社会上的考虑②认为分家是家庭的破裂以及兄弟没有继承一个完整的家庭
作者:分家中也有垂直关系的“继承”、横纵一体的“合”
CPL
①对现有文献的理解和看法②作者在哪个细分领域展开研究
理论基础
RAT
上面两个部分的完善是为这个部分做准备
第二部分:
机制和结构
F(x)
结构:
(1)概念界定:分家的基本内容
什么是分家?分家时财产按照“股”分割;分家的原因
(2)分家带来的影响(案例分析):分家带来了社会流动
借用说“分家三年显高低”、“富不过三代”、“父子一条心,黄土变成金”三句俚语来说明分家对社会变化的影响
(3)分家的中“继”与“合”
继:赡养老人、继宗祧(tiao 1声),对应儒的孝、父子一体观念
合:生产生活上的合作
(4)结语
机制:对应儒的孝、父子一体观念;生产生活上的合作
Argument
CA
分中有继也有合
第三部分:
问题和发展
(1) 文献综述找敌军可以借鉴,以及文献评述
(2) 文献综述可以加一些友军
(3) 文章可能写的太早了,不太符合现在的文章写作规范。不太理解第二部分“分家对社会发展的影响”对整篇文章有什么关系??是不是没有必要占这么大篇幅
(4) 内容方面:
随着时间的演变,他们的合越来越局限于小,男女双方的直系亲属,直系的兄弟关系和姻亲关系,大家族的联系越来越少;大家族即使祖坟放在一起,也难以通过祭祀的手段联系起来,慢慢农村也形成原子化的家庭单位,对于同村的人来说,地缘关系、邻里关系是比血缘关系更重要的存在

参考文献

1.https://daringfireball.net/projects/markdown/syntax
2.https://www.webfx.com/tools/emoji-cheat-sheet/
3.https://guides.github.com/features/mastering-markdown/
4.https://github.com/mxxhcm/use_vim_as_ide#8.4
5.https://chaxiaoniu.oschina.io/2017/07/10/HexoAddEmoji/
6.https://www.markdownguide.org/basic-syntax/

tensorflow 常见问题(不定期更新)

发表于 2019-03-07 | 更新于 2019-12-17 | 分类于 tensorflow

问题1-The value of a feed cannot be a tf.Tensor object

报错

1
TypeError: The value of a feed cannot be a tf.Tensor object

问题原因

sess.run(op, feed_dict={})中的feed value不能是tf.Tensor类型。

解决方法

sess.run(train, feed_dict={x:images, y:labels}的输入不能是tensor,可以使用sess.run(tensor)得到numpy.array形式的数据再喂给feed_dict。

Once you have launched a sess, you can use your_tensor.eval(session=sess) or sess.run(your_tensor) to get you feed tensor into the format of numpy.array and then feed it to your placeholder.

问题2-Could not create cudnn handle: CUDNN_STATUS_INTERNAL_ERROR

配置

环境配置如下:

  • Ubuntu 18.04
  • CUDA 10.0
  • CuDNN 7.4.2
  • Python3.7.3
  • Tensorflow 1.13.1
  • Nvidia Drivers 430.09
  • RTX2070

报错

1
2
3
4
...
2019-05-12 14:45:59.355405: E tensorflow/stream_executor/cuda/cuda_dnn.cc:334] Could not create cudnn handle: CUDNN_STATUS_INTERNAL_ERROR
2019-05-12 14:45:59.357698: E tensorflow/stream_executor/cuda/cuda_dnn.cc:334] Could not create cudnn handle: CUDNN_STATUS_INTERNAL_ERROR
...

问题原因

GPU不够用了。

解决方法

在代码中添加下面几句:

1
2
3
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
session = InteractiveSession(config=config)

问题3-libcublas.so.10.0: cannot open shared object file: No such file or directory

在命令行或者pycharm中import tensorflow报错

报错

1
2
ImportError: libcublas.so.10.0: cannot open shared object file: No such file or directory
Failed to load the native TensorFlow runtime.

问题原因

没有配置CUDA环境变量

解决方法

命令行中

在.bashrc文件中加入下列语句:

1
2
3
export PATH=/usr/local/cuda/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
export CUDA_HOME=/usr/local/cuda

pycharm中

方法1(这种方法我没有实验成功,不知道为什么)

在左上角选中
File>>Settings>>Build.Execution,Deployment>>Console>>Python Console
在Environment下的Environment variables中添加
LD_LIBRARY_PATH=/usr/local/cuda/lib64:${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}即可。

方法2

修改完.bashrc文件后从终端中运行pycharm。

问题4-dlerror: libcupti.so.10.0: cannot open shared object file: No such file or directory

执行mnist_with_summary代码时报错

报错

1
2
3
I tensorflow/stream_executor/dso_loader.cc:142] Couldn't open CUDA library libcupti.so.10.0. LD_LIBRARY_PATH: /usr/local/cuda/lib64:
2019-05-13 23:04:10.620149: F tensorflow/stream_executor/lib/statusor.cc:34] Attempting to fetch value instead of handling error Failed precondition: could not dlopen DSO: libcupti.so.10.0; dlerror: libcupti.so.10.0: cannot open shared object file: No such file or directory
Aborted (core dumped)

问题问题问题问题问题问题问题问题问题原因

libcupti.so.10.0包没找到

解决方法

执行以下命令,找到相关的依赖包:
~$:find /usr/local/cuda/ -name libcupti.so.10.0
输出如下:

/usr/local/cuda/extras/CUPTI/lib64/libcupti.so.10.0

然后修改~/.bashrc文件中相应的环境变量:
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/local/cuda/extras/CUPTI/lib64/😒{LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
重新运行即可。

问题5-unhashable type: ‘list’

sess.run(op, feed_dict={})中feed的数据中包含有list的时候会报错。

报错

1
TypeError: unhashable type: 'list'

问题原因

feed_dict中不能的value不能是list。

解决方法

1
2
3
4
feed_dict = {
placeholder : value
for placeholder, value in zip(placeholder_list, inputs_list))
}

代码示例

代码地址

问题6-Attempting to use uninitialized value

tf.Session()和tf.InteractiveSession()混用问题。

报错

1
2
3
tensorflow.python.framework.errors_impl.FailedPreconditionError: Attempting to use uninitialized value prediction/l1/w
[[{{node prediction/l1/w/read}}]]
[[{{node prediction/LogSoftmax}}]]

问题原因

声明了如下session:

1
2
sess = tf.Session()
sess.run(tf.global_variables_initializer())

在接下来的代码中,因为我声明的是tf.Session(),使用了op.eval()函数,这种用法是tf.InteractiveSession的用法,所以就相当于没有初始化。
result = op.eval(feed_dict={})
然后就报了未初始化的错误。
把代码改成:
result = sess.run([op], feeed_dct={})
即可,即上下文使用的session应该一致。

解决方案

使用统一的session类型

问题7-setting an array element with a sequence

feed_dict键值对中中值必须是numpy.ndarray,不能是其他类型。

报错

1
value error setting an array element with a sequence,

问题原因

feed_dict中key-value的value必须是numpy.ndarray,不能是其他类型,尤其不能是tf.Variable。

解决方法

检查sess.run(op, feed_dict={})中的feed_dict,确保他们的类型,不能是tf.Variable()类型的对象,需要是numpy.ndarray。

问题8-访问tf.Variable()的值

如何获得tf.Variable()对象的值

解决方法

1
2
3
4
5
import tensorflow as tf
x = tf.Varialbe([1.0, 2.0])
sess = tf.Session()
sess.run(tf.global_variables_initializer())
value = sess.run(x)

或者

1
2
3
4
5
import tensorflow as tf
x = tf.Varialbe([1.0, 2.0])
sess = tf.InteractiveSession()
sess.run(tf.global_variables_initializer())
x.eval()

问题9-Can not convert a ndarray into a Tensor or Operation

报错

1
Can not convert a ndarray into a Tensor or Operation.

问题原因

原因是sess.run()前后参数名重了,比如outputs = sess.run(outputs),outputs本来是自己定义的一个op,但是sess.run(outputs)之后outputs就成了一个变量,就把定义的outputs op覆盖了。

解决方法

换个变量名字就行

问题10-本地使用gpu server的tensorboard

问题描述

在gpu server跑的实验结果,然后summary的记录也在server上,但是又没办法可视化,只好在本地可视化。

解决方法

使用ssh进行映射好了。

本机设置

~$:ssh -L 12345:10.1.114.50:6006 mxxmhh@127.0.0.1
将本机的12345端口映射到10.1.114.50的6006端口,中间服务器使用的是本机。
或者可以使用10.1.114.50作为中间服务器。
~$:ssh -L 12345:10.1.114.50:6006 liuchi@10.1.114.50
或者可以使用如下方法:
~$:ssh -L 12345:127.0.0.1:6006 liuchi@10.1.114.50
从这个方法中,可以看出127.0.0.1这个ip是中间服务器可以访问的ip。
以上三种方法中,-L后的端口号12345可以随意设置,只要不冲突即可。

服务端设置

然后在服务端运行以下命令:
~$:tensorboard --logdir logdir -port 6006
这个端口号也是可以任意设置的,不冲突即可。

运行

然后在本机访问
https://127.0.0.1:12345即可。

问题11-每一步summary一个list的每一个元素

问题原因

有一个tf list的placeholder,但是每一步只能生成其中的一个元素,所以怎么样summary中其中的某一个?

解决方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import tensorflow as tf
import numpy as np

number = 3
x_ph_list = []
for i in range(number):
x_ph_list.append(tf.placeholder(tf.float32, shape=None))

x_summary_list = []
for i in range(number):
x_summary_list.append(tf.summary.scalar("x%s" % i, x_ph_list[i]))

writer = tf.summary.FileWriter("./tf_summary/scalar_list_summary/sep")
with tf.Session() as sess:
scope = 10
inputs = np.arange(scope*number)
inputs = inputs.reshape(scope, number)
# inputs = np.random.randn(scope, number)
for i in range(scope):
for j in range(number):
out, xj_s = sess.run([x_ph_list[j], x_summary_list[j]], feed_dict={x_ph_list[j]: inputs[i][j]})
writer.add_summary(xj_s, global_step=i)

问题12- for value in summary.value: AttributeError: ‘list’ object has no attribute ‘value’

问题描述

writer.add_summary时报错

报错

1
2
3
File "/home/mxxmhh/anaconda3/lib/python3.7/site-packages/tensorflow/python/summary/writer/writer.py", line 127, in add_summary
for value in summary.value:
AttributeError: 'list' object has no attribute 'value'

问题原因

执行以下代码

1
2
s_ = sess.run([loss_summary], feed_dict={p_losses_ph: inputs1, q_losses_ph: inputs2})
writer.add_summary(s_, global_step=1)

因为[loss_summary]加了方括号,就把它当成了一个list。。返回值也是list,就报错了

解决方法

  • 方法1,在等号左边加一个逗号,取出list中的值
1
s_, = sess.run([loss_summary], feed_dict={p_losses_ph: inputs1, q_losses_ph: inputs2})
  • 方法2,去掉loss_summary外面的中括号。
1
s_ = sess.run(loss_summary, feed_dict={p_losses_ph: inputs1, q_losses_ph: inputs2})

问题13- tf.get_default_session() always returns None type:

问题描述

调用tf.get_default_session()时,返回的是None

报错

1
2
    tf.get_default_session().run(y)
AttributeError: 'NoneType' object has no attribute 'run'

问题原因

只有在设定default session之后,才能使用tf.get_default_session()获得当前的默认session,在我们写代码的时候,一般会按照下面的方式写:

1
2
3
4
5
import tensorflow as tf

with tf.Session() as sess:
some operations
...

这种情况下已经把tf.Session()生成的session当做了默认session,但是如果仅仅使用以下代码:

1
2
3
4
5
import tensorflow as tf

sess = tf.Session()
sess.run(some operations)
...

是没有把tf.Session()当成默认session的,即只有在with block内,才会将这个session当做默认session。

解决方案

参考文献

1.https://github.com/tensorflow/tensorflow/issues/4842
2.https://github.com/tensorflow/tensorflow/issues/24496
3.https://github.com/tensorflow/tensorflow/issues/9530
4.https://stackoverflow.com/questions/51128427/how-to-feed-list-of-values-to-a-placeholder-list-in-tensorflow
5.https://github.com/tensorflow/tensorflow/issues/11897
6.https://stackoverflow.com/questions/34156639/tensorflow-python-valueerror-setting-an-array-element-with-a-sequence-in-t
7.https://stackoverflow.com/questions/33679382/how-do-i-get-the-current-value-of-a-variable
8.https://blog.csdn.net/michael__corleone/article/details/79007425
9.https://stackoverflow.com/questions/47721792/tensorflow-tf-get-default-session-after-sess-tf-session-is-none

linux-查看python package的安装位置

发表于 2019-03-04 | 更新于 2019-05-12 | 分类于 linux

使用pip install package-name之后,不知道该包存在了哪个路径下。
可以再次使用pip install package-name,这时候就会给出该包存放在哪个路径下。

参考文献

  1. https://blog.csdn.net/weixin_41712059/article/details/82940516
1…303132…34
马晓鑫爱马荟荟

马晓鑫爱马荟荟

记录硕士三年自己的积累

337 日志
26 分类
77 标签
RSS
GitHub E-Mail
© 2022 马晓鑫爱马荟荟
由 Hexo 强力驱动 v3.8.0
|
主题 – NexT.Pisces v6.6.0