Theano简单入门(一):Theano与Lasagne的安装

一、介绍

      Theano是一个Python库,专门用于定义、优化、求值数学表达式,效率高,适用于多维数组。特别适合做机器学习。一般来说,使用时需要安装python和numpy。

     首先回顾一下机器学习的东西,定义一个模型(函数)f(x;w) x为输入,w为模型参数,然后定义一个损失函数c(f),通过数据驱动在一堆模型函数中选择最优的函数就是训练training的过程,在机器学习中训练一般采用梯度下降法gradient descent。

     使用theano来搭建机器学习(深度学习)框架,有以下优点:

     1、 theano能够自动计算梯度

     2、只需要两步骤就能搭建框架,定义函数和计算梯度。

二、安装

1、安装要求

①python 2 >=2.6 or python 3>=3.3

②Numpy >= 1.7.1

③Scipy >= 0.11

2、通用安装方法

# python 2+ 版本
pip install theano

# python 3+ 版本
pip3 install theano

3、最简单的安装方式是安装Anaconda之后,利用conda命令方式安装theano

3.1 什么是Anaconda?

简单来说,Anaconda是Python的包管理器和环境管理器。先来解决一个初学者都会问的问题:我已经安装了Python,那么为什么还需要Anaconda呢?原因有以下几点:

(1)Anaconda附带了一大批常用数据科学包,它附带了conda、Python和 150 多个科学包及其依赖项。因此你可以用Anaconda立即开始处理数据。

(2)管理包。Anaconda 是在 conda(一个包管理器和环境管理器)上发展出来的。在数据分析中,你会用到很多第三方的包,而conda(包管理器)可以很好的帮助你在计算机上安装和管理这些包,包括安装、卸载和更新包。

(3)管理环境。为什么需要管理环境呢?比如你在A项目中用到了Python2,而新的项目要求使用Python3,而同时安装两个Python版本可能会造成许多混乱和错误。这时候conda就可以帮助你为不同的项目建立不同的运行环境。还有很多项目使用的包版本不同,比如不同的pandas版本,不可能同时安装两个pandas版本。你要做的应该是在项目对应的环境中创建对应的pandas版本。这时候conda就可以帮你做到。

总结:Anaconda解决了官方Python的两大痛点:

(1)提供了包管理功能,Windows平台安装第三方包经常失败的场景得以解决。

(2)提供环境管理功能,解决了多版本Python并存、切换的问题。

3.2 安装Anaconda

①进入Anaconda官网,直接根据电脑系统类型进行下载不同的版本:Windows、macOS、Linux。

②下载完成后直接安装。安装完成之后会有一个Anaconda Prompt,类似于windows的终端操作,可以输入命令行进行操作。

3.3 Python包管理

(1)安装包

conda 的包管理功能和pip 是一样的,当然你选择pip 来安装包也是没问题的。

# 安装 matplotlib 
conda install matplotlib 

(2)卸载包

# 删除包
conda remove matplotlib

(3)更新包

# 包更新
conda update matplotlib

(4)查询已经安装的包

# 查看已安装的包
conda list 

(5)修改镜像地址

①.修改Anaconda镜像地址

安装Anaconda时候,访问的是国外的网络,所以下载Anaconda和安装包时会特别慢。我们需要更换到国内镜像源地址,这里我更换到国内的清华大学地址。(永久添加镜像)Windows命令:

conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --set show_channel_urls yes

②.修改pip镜像地址

如果你安装包时用的是pip,感觉也很慢。同样的,我们把pip的镜像源地址改成国内的,豆瓣源速度比较快。(临时修改的方法)Windows命令:

可以在使用pip的时候加参数-i https://pypi.tuna.tsinghua.edu.cn/simple
#例如,这样就会从清华这边的镜像去安装numpy库。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy

当然,pip还有永久修改,一劳永逸的办法,windows下,直接在user目录中创建一个pip目录,如:C:\Users\xx\pip,新建文件pip.ini,内容如下:

[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple

3.4 管理环境

conda 可以为你不同的项目建立不同的运行环境。

(1)创建环境

conda create –n python27 numpy

上面的命令中,python27是设置环境的名称(-n是指该命令后面的python27是你要创建环境的名称),numpy是你要安装在环境中的包名称。

注意:创建环境时,可以指定要安装在环境中的Python版本。当你同时使用 Python 2.x 和 Python 3.x 中的代码时这很有用。要创建具有特定 Python 版本的环境,例如创建环境名称为python36,并安装最新版本的Python3.6在终端中输入:

conda create –n python36 python=3.6

或也可以这样创建环境名称为python27,并安装最新版本Python2.7:

conda create –n python27 python=2.7

(2)进入环境

在 Windows 上,你可以使用:

conda activate python27

进入。进入之后,你可以在终端提示符中看到环境名称。当然,当你进入环境后,可以用conda list 查看环境中默认的安装包。

(3)离开环境

在 Windows 上,终端中输入:

deactivate

(4)共享环境

共享环境非常有用,它能让其他人安装你代码中使用的所有包,并确保这些包的版本正确。比如你开发了一个药店数据分析系统,你要提交给项目部署系统的人来部署你的项目,但是他们并不知道你当时开发时使用的是哪个python版本,以及使用了哪些包和包的版本。这怎么办呢?你可以在你当前的环境的终端中使用:

conda env export > environment.yaml

将你当前的环境保存到文件中包保存为YAML文件(包括Pyhton版本和所有包的名称)。命令的第一部分 conda env export 用于输出环境中的所有包的名称(包括 Python 版本)。你在终端中上可以看到导出的环境文件路径。在 GitHub 上共享代码时,最好同样创建环境文件并将其包括在代码库中。这能让其他人更轻松地安装你的代码的所有依赖项。

那么问题来了:导出的环境文件,在其他电脑环境中如何使用呢?

首先在conda中进入你的环境,比如conda activate python27。然后在使用以下命令更新你的环境:

#其中-f表示你要导出文件在本地的路径,所以/path/to/environment.yml要换成你本地的实际路径
conda env update -f=/path/to/environment.yml

对于不使用conda 的用户,我们通常还会使用以下命令将一个 txt文件导出并包括在其中:

pip freeze > environment.txt 

然后我将该文件包含在项目的代码库中,其他项目成员即使在他的电脑上没有安装conda也可以使用该文件来安装和我一样的开发环境。

(5)列出环境

有时候会忘记自己创建的环境名称,这时候用 conda env list 就可以列出你创建的所有环境。

你会看到环境的列表,而且你当前所在环境的旁边会有一个星号。默认的环境(即当你不在选定环境中时使用的环境)名为 base。

(6)删除环境

如果你不再使用某个环境,可以使用以下命令。

#删除指定的环境(在这里环境名为 python27)。
conda env remove -n python27

3.5 新建theano环境:

conda create –n theano python=3.5

3.6 进入theano环境,利用conda安装theano:

# 进入环境
activate theano
# 安装theano
conda install theano

三、lasagne的安装

1. 介绍

lasagne意味千层饼,是基于theano之上主要用于建立和训练神经网络的深度学习库。Lasagne is a lightweight library to build and train neural networks in Theano.

网站链接:https://github.com/Lasagne/Lasagne、 lasagne官网教程

主要特点有:

(1)支持所有的前馈神经网络的模型,包括CNNs、RNN+LSTM以及任何扩展的卷积神经网络。

Supports feed-forward networks such as Convolutional Neural Networks (CNNs), recurrent networks including Long Short-Term Memory (LSTM), and any combination thereof

(2)支持多输入和多输出的网络框架、包括额外附加的分类器

Allows architectures of multiple inputs and multiple outputs, including auxiliary classifiers

(3)拥有多种训练的梯度优化算法。Nesterov momentum, RMSprop and ADAM

(4)继承theano的优点,它拥有theano的所有常见的损失函数以及无需自行计算梯度。

Freely definable cost function and no need to derive gradients due to Theano's symbolic differentiation

(5)通过设置脚本的配置文件,支持CPUs和GPUs之间运行的转换。

Transparent support of CPUs and GPUs due to Theano's expression compiler

设计的目的:

(1)简易性:易于使用和扩展的机器学习库Be easy to use, easy to understand and easy to extend, to facilitate use in research

(2)透明性: Do not hide Theano behind abstractions, directly process and return Theano expressions or Python / numpy data types

(3)模块化: Allow all parts (layers, regularizers, optimizers, ...) to be used independently of Lasagne(4)实用性(Pragmatism): Make common use cases easy, do not overrate uncommon cases

(5)限制Restraint: Do not obstruct(阻塞) users with features they decide not to use

(6)集中性: "Do one thing and do it well"

2. 安装

2.1 安装方式

①稳定版安装
执行下面两条命令即可:

pip install -r https://raw.githubusercontent.com/Lasagne/Lasagne/v0.1/requirements.txt
pip install Lasagne==0.1

Bleeding-edge version
执行下面两条命令:

pip install --upgrade https://github.com/Theano/Theano/archive/master.zip
pip install --upgrade https://github.com/Lasagne/Lasagne/archive/master.zip

开发版安装
执行下面命令

git clone https://github.com/Lasagne/Lasagne.git
cd Lasagne
pip install -r requirements.txt
pip install --editable

这里建议安装Bleeding-edge version,功能相对比较新,而版本也相对稳定。

2.2 测试安装

import lasagne
import theano
import theano.tensor as T
 
# create Theano variables for input and target minibatch
input_var = T.tensor4('X')
target_var = T.ivector('y')
 
# create a small convolutional neural network
from lasagne.nonlinearities import leaky_rectify, softmax
network = lasagne.layers.InputLayer((None, 3, 32, 32), input_var)
network = lasagne.layers.Conv2DLayer(network, 64, (3, 3),
                                     nonlinearity=leaky_rectify)
network = lasagne.layers.Conv2DLayer(network, 32, (3, 3),
                                     nonlinearity=leaky_rectify)
network = lasagne.layers.Pool2DLayer(network, (3, 3), stride=2, mode='max')
network = lasagne.layers.DenseLayer(lasagne.layers.dropout(network, 0.5),
                                    128, nonlinearity=leaky_rectify,
                                    W=lasagne.init.Orthogonal())
 
network = lasagne.layers.DenseLayer(lasagne.layers.dropout(network, 0.5),
                                    10, nonlinearity=softmax)
 
# create loss function
prediction = lasagne.layers.get_output(network)
loss = lasagne.objectives.categorical_crossentropy(prediction, target_var)
loss = loss.mean() + 1e-4 * lasagne.regularization.regularize_network_params(
        network, lasagne.regularization.l2)
# create parameter update expressions
params = lasagne.layers.get_all_params(network, trainable=True)
updates = lasagne.updates.nesterov_momentum(loss, params, learning_rate=0.01,
                                            momentum=0.9)
# compile training function that updates parameters and returns training loss
train_fn = theano.function([input_var, target_var], loss, updates=updates)
 
# train network (assuming you've got some training data in numpy arrays)
for epoch in range(100):
    loss = 0
    for input_batch, target_batch in training_data:
loss += train_fn(input_batch, target_batch)
    print("Epoch %d: Loss %g" % (epoch + 1, loss / len(training_data)))
 
# use trained network for predictions
test_prediction = lasagne.layers.get_output(network, deterministic=True)
predict_fn = theano.function([input_var], T.argmax(test_prediction, axis=1))
print("Predicted class for first test input: %r" % predict_fn(test_data[0]))

测试安装过程中遇见了错误,是因为theano里面的文件变化了,没有downsample文件了,所有有些函数变到其他文件了,所以专门再次记录一下:

在较早的版本中,可能会使用from theano.tensor.signal.downsample import max_pool_2d。根据运行提示,更新到 from theano.tensor.signal.pool import pool_2d 中了。查看了一下theano下面的包,发现在signal(例如我的目录:D:\Anaconda3\envs\theano\Lib\site-packages\theano\tensor\signal)下面没有了downsample了,只有pool和conv了。如果以后再用downsample的时候,很可能就是调用这两个包里面的东西,改一下就好了。出问题的文件在pool.py文件中,所以我们需要对其进行修改。

在你安装lasagne的文件下,conda环境中可以的环境下可以找到(例如我的Anaconda安装在D:盘,theano安装在虚拟的theano环境下,所以lasagne下的pool.py文件在:(D:\Anaconda3\envs\theano\Lib\site-packages\lasagne\layers)

需要对其进行修改,修改之处有三,注意查看。

import theano.tensor as T

from .base import Layer
from ..utils import as_tuple


#修改之处①。不再引用downsample 
#from theano.tensor.signal.pool import downsample
from theano.tensor.signal import pool

__all__ = [
    "MaxPool1DLayer",
    "MaxPool2DLayer",
    "Pool2DLayer",
    "FeaturePoolLayer",
    "FeatureWTALayer",
    "GlobalPoolLayer",
]


def pool_output_length(input_length, pool_size, stride, pad, ignore_border):
    if input_length is None or pool_size is None:
        return None

    if ignore_border:
        output_length = input_length + 2 * pad - pool_size + 1
        output_length = (output_length + stride - 1) // stride

    else:
        assert pad == 0

        if stride >= pool_size:
            output_length = (input_length + stride - 1) // stride
        else:
            output_length = max(
                0, (input_length - pool_size + stride - 1) // stride) + 1

    return output_length


class MaxPool1DLayer(Layer):

    def __init__(self, incoming, pool_size, stride=None, pad=0,
                 ignore_border=True, **kwargs):
        super(MaxPool1DLayer, self).__init__(incoming, **kwargs)
        self.pool_size = as_tuple(pool_size, 1)
        self.stride = self.pool_size if stride is None else as_tuple(stride, 1)
        self.pad = as_tuple(pad, 1)
        self.ignore_border = ignore_border

    def get_output_shape_for(self, input_shape):
        output_shape = list(input_shape)  # copy / convert to mutable list

        output_shape[-1] = pool_output_length(input_shape[-1],
                                              pool_size=self.pool_size[0],
                                              stride=self.stride[0],
                                              pad=self.pad[0],
                                              ignore_border=self.ignore_border,
                                              )

        return tuple(output_shape)

    def get_output_for(self, input, **kwargs):
        input_4d = T.shape_padright(input, 1)
        #修改之处②,原来的函数变化了一下,主要是方法变了
        #pooled = downsample.max_pool_2d(input_4d,
        #                                ds=(self.pool_size[0], 1),
        #                                st=(self.stride[0], 1),
        #                                ignore_border=self.ignore_border,
        #                                padding=(self.pad[0], 0),
        #                                )
        pooled = pool.pool_2d(input_4d,
                              ds=(self.pool_size[0], 1),
                              st=(self.stride[0], 1),
                              ignore_border=self.ignore_border,
                              padding=(self.pad[0], 0),
                              )

        return pooled[:, :, :, 0]


class Pool2DLayer(Layer):

    def __init__(self, incoming, pool_size, stride=None, pad=(0, 0),
                 ignore_border=True, mode='max', **kwargs):
        super(Pool2DLayer, self).__init__(incoming, **kwargs)

        self.pool_size = as_tuple(pool_size, 2)

        if stride is None:
            self.stride = self.pool_size
        else:
            self.stride = as_tuple(stride, 2)

        self.pad = as_tuple(pad, 2)

        self.ignore_border = ignore_border
        self.mode = mode

    def get_output_shape_for(self, input_shape):
        output_shape = list(input_shape)  # copy / convert to mutable list

        output_shape[2] = pool_output_length(input_shape[2],
                                             pool_size=self.pool_size[0],
                                             stride=self.stride[0],
                                             pad=self.pad[0],
                                             ignore_border=self.ignore_border,
                                             )

        output_shape[3] = pool_output_length(input_shape[3],
                                             pool_size=self.pool_size[1],
                                             stride=self.stride[1],
                                             pad=self.pad[1],
                                             ignore_border=self.ignore_border,
                                             )

        return tuple(output_shape)

    def get_output_for(self, input, **kwargs):
        # 修改之处③,方法变了,属性ds也变成了ws
        #pooled = downsample.max_pool_2d(input,
        #                                ds=self.pool_size,
        #                                st=self.stride,
        #                                ignore_border=self.ignore_border,
        #                                padding=self.pad,
        #                                mode=self.mode,
        #                                )
        pooled = pool.pool_2d(input,
                              ws=self.pool_size,
                              ignore_border=self.ignore_border,
                              padding=self.pad,
                              mode=self.mode,
                              )
        return pooled


class MaxPool2DLayer(Pool2DLayer):

    def __init__(self, incoming, pool_size, stride=None, pad=(0, 0),
                 ignore_border=True, **kwargs):
        super(MaxPool2DLayer, self).__init__(incoming,
                                             pool_size,
                                             stride,
                                             pad,
                                             ignore_border,
                                             mode='max',
                                             **kwargs)

# TODO: add reshape-based implementation to MaxPool*DLayer
# TODO: add MaxPool3DLayer


class FeaturePoolLayer(Layer):

    def __init__(self, incoming, pool_size, axis=1, pool_function=T.max,
                 **kwargs):
        super(FeaturePoolLayer, self).__init__(incoming, **kwargs)
        self.pool_size = pool_size
        self.axis = axis
        self.pool_function = pool_function

        num_feature_maps = self.input_shape[self.axis]
        if num_feature_maps % self.pool_size != 0:
            raise ValueError("Number of input feature maps (%d) is not a "
                             "multiple of the pool size (pool_size=%d)" %
                             (num_feature_maps, self.pool_size))

    def get_output_shape_for(self, input_shape):
        output_shape = list(input_shape)  # make a mutable copy
        output_shape[self.axis] = input_shape[self.axis] // self.pool_size
        return tuple(output_shape)

    def get_output_for(self, input, **kwargs):
        input_shape = tuple(input.shape)
        num_feature_maps = input_shape[self.axis]
        num_feature_maps_out = num_feature_maps // self.pool_size

        pool_shape = (input_shape[:self.axis] +
                      (num_feature_maps_out, self.pool_size) +
                      input_shape[self.axis+1:])

        input_reshaped = input.reshape(pool_shape)
        return self.pool_function(input_reshaped, axis=self.axis + 1)


class FeatureWTALayer(Layer):

    def __init__(self, incoming, pool_size, axis=1, **kwargs):
        super(FeatureWTALayer, self).__init__(incoming, **kwargs)
        self.pool_size = pool_size
        self.axis = axis

        num_feature_maps = self.input_shape[self.axis]
        if num_feature_maps % self.pool_size != 0:
            raise ValueError("Number of input feature maps (%d) is not a "
                             "multiple of the region size (pool_size=%d)" %
                             (num_feature_maps, self.pool_size))

    def get_output_for(self, input, **kwargs):
        num_feature_maps = input.shape[self.axis]
        num_pools = num_feature_maps // self.pool_size

        pool_shape = ()
        arange_shuffle_pattern = ()
        for k in range(self.axis):
            pool_shape += (input.shape[k],)
            arange_shuffle_pattern += ('x',)

        pool_shape += (num_pools, self.pool_size)
        arange_shuffle_pattern += ('x', 0)

        for k in range(self.axis + 1, input.ndim):
            pool_shape += (input.shape[k],)
            arange_shuffle_pattern += ('x',)

        input_reshaped = input.reshape(pool_shape)
        max_indices = T.argmax(input_reshaped, axis=self.axis + 1,
                               keepdims=True)

        arange = T.arange(self.pool_size).dimshuffle(*arange_shuffle_pattern)
        mask = T.eq(max_indices, arange).reshape(input.shape)

        return input * mask


class GlobalPoolLayer(Layer):

    def __init__(self, incoming, pool_function=T.mean, **kwargs):
        super(GlobalPoolLayer, self).__init__(incoming, **kwargs)
        self.pool_function = pool_function

    def get_output_shape_for(self, input_shape):
        return input_shape[:2]

    def get_output_for(self, input, **kwargs):
        return self.pool_function(input.flatten(3), axis=2)

 

 

你可能感兴趣的:(生成模型,python)