手把手教你由TensorFlow上手PyTorch(附代码)

当我第一次尝试学习 PyTorch 时,没几天就放弃了。和 TensorFlow 相比,我很难弄清 PyTorch 的核心要领。但是随后不久,PyTorch 发布了一个新版本,我决定重新来过。在第二次的学习中,我开始了解这个框架的易用性。在本文中,我会简要解释 PyTorch 的核心概念,为你转入这个框架提供一些必要的动力。其中包含了一些基础概念,以及先进的功能如学习速率调整、自定义层等等。

 


PyTorch 的易用性如何?Andrej Karpathy 是这样评价的

资源

首先要知道的是:PyTorch 的主目录和教程是分开的。而且因为开发和版本更新的速度过快,有时候两者之间并不匹配。所以你需要不时查看源代码:http://pytorch.org/tutorials/。

当然,目前网络上已有了一些 PyTorch 论坛,你可以在其中询问相关的问题,并很快得到回复:https://discuss.pytorch.org/。

 

把 PyTorch 当做 NumPy 用

让我们先看看 PyTorch 本身,其主要构件是张量——这和 NumPy 看起来差不多。这种性质使得 PyTorch 可支持大量相同的 API,所以有时候你可以把它用作是 NumPy 的替代品。PyTorch 的开发者们这么做的原因是希望这种框架可以完全获得 GPU 加速带来的便利,以便你可以快速进行数据预处理,或其他任何机器学习任务。将张量从 NumPy 转换至 PyTorch 非常容易,反之亦然。让我们看看如下代码:


  1. import torch
  2. import numpy as np
  3. numpy_tensor = np.random.randn(10, 20)
  4. # convert numpy array to pytorch array
  5. pytorch_tensor = torch.Tensor(numpy_tensor)
  6. # or another way
  7. pytorch_tensor = torch.from_numpy(numpy_tensor)
  8. # convert torch tensor to numpy representation
  9. pytorch_tensor.numpy()
  10. # if we want to use tensor on GPU provide another type
  11. dtype = torch.cuda.FloatTensor
  12. gpu_tensor = torch.randn(10, 20).type(dtype)
  13. # or just call `cuda()` method
  14. gpu_tensor = pytorch_tensor.cuda()
  15. # call back to the CPU
  16. cpu_tensor = gpu_tensor.cpu()
  17. # define pytorch tensors
  18. x = torch.randn(10, 20)
  19. y = torch.ones(20, 5)
  20. # `@` mean matrix multiplication from python3.5, PEP-0465
  21. res = x @ y
  22. # get the shape
  23. res.shape  # torch.Size([10, 5])

从张量到变量

张量是 PyTorch 的一个完美组件,但是要想构建神经网络这还远远不够。反向传播怎么办?当然,我们可以手动实现它,但是真的需要这样做吗?幸好还有自动微分。为了支持这个功能,PyTorch 提供了变量,它是张量之上的封装。如此,我们可以构建自己的计算图,并自动计算梯度。每个变量实例都有两个属性:包含初始张量本身的.data,以及包含相应张量梯度的.grad


  1. import torch
  2. from torch.autograd import Variable
  3. # define an inputs
  4. x_tensor = torch.randn(10, 20)
  5. y_tensor = torch.randn(10, 5)
  6. x = Variable(x_tensor, requires_grad=False)
  7. y = Variable(y_tensor, requires_grad=False)
  8. # define some weights
  9. w = Variable(torch.randn(20, 5), requires_grad=True)
  10. # get variable tensor
  11. print(type(w.data))  # torch.FloatTensor
  12. # get variable gradient
  13. print(w.grad)  # None
  14. loss = torch.mean((y - x @ w) ** 2)
  15. # calculate the gradients
  16. loss.backward()
  17. print(w.grad)  # some gradients
  18. # manually apply gradients
  19. w.data -= 0.01 * w.grad.data
  20. # manually zero gradients after update
  21. w.grad.data.zero_()

你也许注意到我们手动计算了自己的梯度,这样看起来很麻烦,我们能使用优化器吗?当然。


  1. import torch
  2. from torch.autograd import Variable
  3. import torch.nn.functional as F
  4. x = Variable(torch.randn(10, 20), requires_grad=False)
  5. y = Variable(torch.randn(10, 3), requires_grad=False)
  6. # define some weights
  7. w1 = Variable(torch.randn(20, 5), requires_grad=True)
  8. w2 = Variable(torch.randn(5, 3), requires_grad=True)
  9. learning_rate = 0.1
  10. loss_fn = torch.nn.MSELoss()
  11. optimizer = torch.optim.SGD([w1, w2], lr=learning_rate)
  12. for step in range(5):
  13.    pred = F.sigmoid(x @ w1)
  14.    pred = F.sigmoid(pred @ w2)
  15.    loss = loss_fn(pred, y)
  16.    # manually zero all previous gradients
  17.    optimizer.zero_grad()
  18.    # calculate new gradients
  19.    loss.backward()
  20.    # apply new gradients
  21.    optimizer.step()

并不是所有的变量都可以自动更新。但是你应该可以从最后一段代码中看到重点:我们仍然需要在计算新梯度之前将它手动归零。这是 PyTorch 的核心理念之一。有时我们会不太明白为什么要这么做,但另一方面,这样可以让我们充分控制自己的梯度。

 

静态图 vs 动态图

PyTorch 和 TensorFlow 的另一个主要区别在于其不同的计算图表现形式。TensorFlow 使用静态图,这意味着我们是先定义,然后不断使用它。在 PyTorch 中,每次正向传播都会定义一个新计算图。在开始阶段,两者之间或许差别不是很大,但动态图会在你希望调试代码,或定义一些条件语句时显现出自己的优势。就像你可以使用自己最喜欢的 debugger 一样!

你可以比较一下 while 循环语句的下两种定义——第一个是 TensorFlow 中,第二个是 PyTorch 中:


  1. import tensorflow as tf
  2. first_counter = tf.constant(0)
  3. second_counter = tf.constant(10)
  4. some_value = tf.Variable(15)
  5. # condition should handle all args:
  6. def cond(first_counter, second_counter, *args):
  7.    return first_counter < second_counter
  8. def body(first_counter, second_counter, some_value):
  9.    first_counter = tf.add(first_counter, 2)
  10.    second_counter = tf.add(second_counter, 1)
  11.    return first_counter, second_counter, some_value
  12. c1, c2, val = tf.while_loop(
  13.    cond, body, [first_counter, second_counter, some_value])
  14. with tf.Session() as sess:
  15.    sess.run(tf.global_variables_initializer())
  16.    counter_1_res, counter_2_res = sess.run([c1, c2])

  1. import torch
  2. first_counter = torch.Tensor([0])
  3. second_counter = torch.Tensor([10])
  4. some_value = torch.Tensor(15)
  5. while (first_counter < second_counter)[0]:
  6.    first_counter += 2
  7.    second_counter += 1

看起来第二种方法比第一个简单多了,你觉得呢?

 

模型定义

现在我们看到,想在 PyTorch 中创建 if/else/while 复杂语句非常容易。不过让我们先回到常见模型中,PyTorch 提供了非常类似于 Keras 的、即开即用的层构造函数:

神经网络包(nn)定义了一系列的模块,它可以粗略地等价于神经网络的层。模块接收输入变量并计算输出变量,但也可以保存内部状态,例如包含可学习参数的变量。nn 包还定义了一组在训练神经网络时常用的损失函数。


  1. from collections import OrderedDict
  2. import torch.nn as nn
  3. # Example of using Sequential
  4. model = nn.Sequential(
  5.    nn.Conv2d(1, 20, 5),
  6.    nn.ReLU(),
  7.    nn.Conv2d(20, 64, 5),
  8.    nn.ReLU()
  9. )
  10. # Example of using Sequential with OrderedDict
  11. model = nn.Sequential(OrderedDict([
  12.    ('conv1', nn.Conv2d(1, 20, 5)),
  13.    ('relu1', nn.ReLU()),
  14.    ('conv2', nn.Conv2d(20, 64, 5)),
  15.    ('relu2', nn.ReLU())
  16. ]))
  17. output = model(some_input)

如果你想要构建复杂的模型,我们可以将 nn.Module 类子类化。当然,这两种方式也可以互相结合。


  1. from torch import nn
  2. class Model(nn.Module):
  3.    def __init__(self):
  4.        super().__init__()
  5.        self.feature_extractor = nn.Sequential(
  6.            nn.Conv2d(3, 12, kernel_size=3, padding=1, stride=1),
  7.            nn.Conv2d(12, 24, kernel_size=3, padding=1, stride=1),
  8.        )
  9.        self.second_extractor = nn.Conv2d(
  10.            24, 36, kernel_size=3, padding=1, stride=1)
  11.    def forward(self, x):
  12.        x = self.feature_extractor(x)
  13.        x = self.second_extractor(x)
  14.        # note that we may call same layer twice or mode
  15.        x = self.second_extractor(x)
  16.        return x

在__init__方法中,我们需要定义之后需要使用的所有层。在正向方法中,我们需要提出如何使用已经定义的层的步骤。而在反向传播上,和往常一样,计算是自动进行的。

 

自定义层

如果我们想要定义一些非标准反向传播模型要怎么办?这里有一个例子——XNOR 网络:



在这里我们不会深入细节,如果你对它感兴趣,可以参考一下原始论文:https://arxiv.org/abs/1603.05279

与我们问题相关的是反向传播需要权重必须介于-1 到 1 之间。在 PyTorch 中,这可以很容易实现:


  1. import torch
  2. class MyFunction(torch.autograd.Function):
  3.    @staticmethod
  4.    def forward(ctx, input):
  5.        ctx.save_for_backward(input)
  6.        output = torch.sign(input)
  7.        return output
  8.    @staticmethod
  9.    def backward(ctx, grad_output):
  10.        # saved tensors - tuple of tensors, so we need get first
  11.        input, = ctx.saved_variables
  12.        grad_output[input.ge(1)] = 0
  13.        grad_output[input.le(-1)] = 0
  14.        return grad_output
  15. # usage
  16. x = torch.randn(10, 20)
  17. y = MyFunction.apply(x)
  18. # or
  19. my_func = MyFunction.apply
  20. y = my_func(x)
  21. # and if we want to use inside nn.Module
  22. class MyFunctionModule(torch.nn.Module):
  23.    def forward(self, x):
  24.        return MyFunction.apply(x)

正如你所见,我们应该只定义两种方法:一个为正向传播,一个为反向传播。如果我们需要从正向通道访问一些变量,我们可以将它们存储在 ctx 变量中。注意:在此前的 API 正向/反向传播不是静态的,我们存储变量需要以 self.save_for_backward(input) 的形式,并以 input, _ = self.saved_tensors 的方式接入。

 

在 CUDA 上训练模型

我们曾经讨论过传递一个张量到 CUDA 上。但如果希望传递整个模型,我们可以通过调用.cuda() 来完成,并将每个输入变量传递到.cuda() 中。在所有计算后,我们需要用返回.cpu() 的方法来获得结果。

 

同时,PyTorch 也支持在源代码中直接分配设备


  1. import torch
  2. ### tensor example
  3. x_cpu = torch.randn(10, 20)
  4. w_cpu = torch.randn(20, 10)
  5. # direct transfer to the GPU
  6. x_gpu = x_cpu.cuda()
  7. w_gpu = w_cpu.cuda()
  8. result_gpu = x_gpu @ w_gpu
  9. # get back from GPU to CPU
  10. result_cpu = result_gpu.cpu()
  11. ### model example
  12. model = model.cuda()
  13. # train step
  14. inputs = Variable(inputs.cuda())
  15. outputs = model(inputs)
  16. # get back from GPU to CPU
  17. outputs = outputs.cpu()

因为有些时候我们想在 CPU 和 GPU 中运行相同的模型,而无需改动代码,我们会需要一种封装:


  1. class Trainer:
  2.    def __init__(self, model, use_cuda=False, gpu_idx=0):
  3.        self.use_cuda = use_cuda
  4.        self.gpu_idx = gpu_idx
  5.        self.model = self.to_gpu(model)
  6.    def to_gpu(self, tensor):
  7.        if self.use_cuda:
  8.            return tensor.cuda(self.gpu_idx)
  9.        else:
  10.            return tensor
  11.    def from_gpu(self, tensor):
  12.        if self.use_cuda:
  13.            return tensor.cpu()
  14.        else:
  15.            return tensor
  16.    def train(self, inputs):
  17.        inputs = self.to_gpu(inputs)
  18.        outputs = self.model(inputs)
  19.        outputs = self.from_gpu(outputs)

权重初始化

在 TesnorFlow 中权重初始化主要是在张量声明中进行的。PyTorch 则提供了另一种方法:首先声明张量,随后在下一步里改变张量的权重。权重可以用调用 torch.nn.init 包中的多种方法初始化为直接访问张量的属性。这个决定或许并不直接了当,但当你希望初始化具有某些相同初始化类型的层时,它就会变得有用。


  1. import torch
  2. from torch.autograd import Variable
  3. # new way with `init` module
  4. w = torch.Tensor(3, 5)
  5. torch.nn.init.normal(w)
  6. # work for Variables also
  7. w2 = Variable(w)
  8. torch.nn.init.normal(w2)
  9. # old styled direct access to tensors data attribute
  10. w2.data.normal_()
  11. # example for some module
  12. def weights_init(m):
  13.    classname = m.__class__.__name__
  14.    if classname.find('Conv') != -1:
  15.        m.weight.data.normal_(0.0, 0.02)
  16.    elif classname.find('BatchNorm') != -1:
  17.        m.weight.data.normal_(1.0, 0.02)
  18.        m.bias.data.fill_(0)
  19. # for loop approach with direct access
  20. class MyModel(nn.Module):
  21.    def __init__(self):
  22.        for m in self.modules():
  23.            if isinstance(m, nn.Conv2d):
  24.                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
  25.                m.weight.data.normal_(0, math.sqrt(2. / n))
  26.            elif isinstance(m, nn.BatchNorm2d):
  27.                m.weight.data.fill_(1)
  28.                m.bias.data.zero_()
  29.            elif isinstance(m, nn.Linear):
  30.                m.bias.data.zero_()

反向排除子图

有时,当你希望保留模型中的某些层或者为生产环境做准备的时候,禁用某些层的自动梯度机制非常有用。在这种思路下,PyTorch 设计了两个 flag:requires_grad 和 volatile。第一个可以禁用当前层的梯度,但子节点仍然可以计算。第二个可以禁用自动梯度,同时效果沿用至所有子节点。


  1. import torch
  2. from torch.autograd import Variable
  3. # requires grad
  4. # If there’s a single input to an operation that requires gradient,
  5. # its output will also require gradient.
  6. x = Variable(torch.randn(5, 5))
  7. y = Variable(torch.randn(5, 5))
  8. z = Variable(torch.randn(5, 5), requires_grad=True)
  9. a = x + y
  10. a.requires_grad  # False
  11. b = a + z
  12. b.requires_grad  # True
  13. # Volatile differs from requires_grad in how the flag propagates.
  14. # If there’s even a single volatile input to an operation,
  15. # its output is also going to be volatile.
  16. x = Variable(torch.randn(5, 5), requires_grad=True)
  17. y = Variable(torch.randn(5, 5), volatile=True)
  18. a = x + y
  19. a.requires_grad  # False

训练过程

当然,PyTorch 还有一些其他卖点。例如你可以设定学习速率,让它以特定规则进行变化。或者你可以通过简单的训练标记允许/禁止批规范层和 dropout。如果你想要做的话,让 CPU 和 GPU 的随机算子不同也是可以的。

 


  1. # scheduler example
  2. from torch.optim import lr_scheduler
  3. optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
  4. scheduler = lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)
  5. for epoch in range(100):
  6.    scheduler.step()
  7.    train()
  8.    validate()
  9. # Train flag can be updated with boolean
  10. # to disable dropout and batch norm learning
  11. model.train(True)
  12. # execute train step
  13. model.train(False)
  14. # run inference step
  15. # CPU seed
  16. torch.manual_seed(42)
  17. # GPU seed
  18. torch.cuda.manual_seed_all(42)

同时,你也可以添加模型信息,或存储/加载一小段代码。如果你的模型是由 OrderedDict 或基于类的模型字符串,它的表示会包含层名。


  1. from collections import OrderedDict
  2. import torch.nn as nn
  3. model = nn.Sequential(OrderedDict([
  4.    ('conv1', nn.Conv2d(1, 20, 5)),
  5.    ('relu1', nn.ReLU()),
  6.    ('conv2', nn.Conv2d(20, 64, 5)),
  7.    ('relu2', nn.ReLU())
  8. ]))
  9. print(model)
  10. # Sequential (
  11. #   (conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
  12. #   (relu1): ReLU ()
  13. #   (conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
  14. #   (relu2): ReLU ()
  15. # )
  16. # save/load only the model parameters(prefered solution)
  17. torch.save(model.state_dict(), save_path)
  18. model.load_state_dict(torch.load(save_path))
  19. # save whole model
  20. torch.save(model, save_path)
  21. model = torch.load(save_path)

根据 PyTorch 文档,用 state_dict() 的方式存储文档更好。

 

记录

训练过程的记录是一个非常重要的部分。不幸的是,PyTorch 目前还没有像 Tensorboard 这样的东西。所以你只能使用普通文本记录 Python 了,你也可以试试一些第三方库:

  • logger:https://github.com/oval-group/logger
  • Crayon:https://github.com/torrvision/crayon
  • tensorboard_logger:https://github.com/TeamHG-Memex/tensorboard_logger
  • tensorboard-pytorch:https://github.com/lanpa/tensorboard-pytorch
  • Visdom:https://github.com/facebookresearch/visdom

 

掌控数据

你可能会记得 TensorFlow 中的数据加载器,甚至想要实现它的一些功能。对于我来说,我花了四个小时来掌握其中所有管道的执行原理。

 



 

首先,我想在这里添加一些代码,但我认为上图足以解释它的基础理念了。

PyTorch 开发者不希望重新发明轮子,他们只是想要借鉴多重处理。为了构建自己的数据加载器,你可以从 torch.utils.data.Dataset 继承类,并更改一些方法:


  1. import torch
  2. import torchvision as tv
  3. class ImagesDataset(torch.utils.data.Dataset):
  4.    def __init__(self, df, transform=None,
  5.                 loader=tv.datasets.folder.default_loader):
  6.        self.df = df
  7.        self.transform = transform
  8.        self.loader = loader
  9.    def __getitem__(self, index):
  10.        row = self.df.iloc[index]
  11.        target = row['class_']
  12.        path = row['path']
  13.        img = self.loader(path)
  14.        if self.transform is not None:
  15.            img = self.transform(img)
  16.        return img, target
  17.    def __len__(self):
  18.        n, _ = self.df.shape
  19.        return n
  20. # what transformations should be done with our images
  21. data_transforms = tv.transforms.Compose([
  22.    tv.transforms.RandomCrop((64, 64), padding=4),
  23.    tv.transforms.RandomHorizontalFlip(),
  24.    tv.transforms.ToTensor(),
  25. ])
  26. train_df = pd.read_csv('path/to/some.csv')
  27. # initialize our dataset at first
  28. train_dataset = ImagesDataset(
  29.    df=train_df,
  30.    transform=data_transforms
  31. )
  32. # initialize data loader with required number of workers and other params
  33. train_loader = torch.utils.data.DataLoader(train_dataset,
  34.                                           batch_size=10,
  35.                                           shuffle=True,
  36.                                           num_workers=16)
  37. # fetch the batch(call to `__getitem__` method)
  38. for img, target in train_loader:
  39.    pass

 

有两件事你需要事先知道:

  • PyTorch 的图维度和 TensorFlow 的不同。前者的是 [Batch_size × channels × height × width] 的形式。但如果你没有通过预处理步骤 torchvision.transforms.ToTensor() 进行交互,则可以进行转换。在 transforms 包中还有很多有用小工具。
  • 你很可能会使用固定内存的 GPU。对此,你只需要对 cuda() 调用额外的标志 async = True,并从标记为 pin_memory = True 的 DataLoader 中获取固定批次。

 

最终架构

现在我们了解了模型、优化器和很多其他细节。是时候来个总结了:



这里有一段用于解读的伪代码:


  1. class ImagesDataset(torch.utils.data.Dataset):
  2.    pass
  3. class Net(nn.Module):
  4.    pass
  5. model = Net()
  6. optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
  7. scheduler = lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)
  8. criterion = torch.nn.MSELoss()
  9. dataset = ImagesDataset(path_to_images)
  10. data_loader = torch.utils.data.DataLoader(dataset, batch_size=10)
  11. train = True
  12. for epoch in range(epochs):
  13.    if train:
  14.        lr_scheduler.step()
  15.    for inputs, labels in data_loader:
  16.        inputs = Variable(to_gpu(inputs))
  17.        labels = Variable(to_gpu(labels))
  18.        outputs = model(inputs)
  19.        loss = criterion(outputs, labels)
  20.        if train:
  21.            optimizer.zero_grad()
  22.            loss.backward()
  23.            optimizer.step()
  24.    if not train:
  25.        save_best_model(epoch_validation_accuracy)

结论

希望本文可以让你了解 PyTorch 的如下特点:

  • 它可以用来代替 Numpy
  • 它的原型设计非常快
  • 调试和使用条件流非常简单
  • 有很多方便且开箱即用的工具

 

PyTorch 是一个正在快速发展的框架,背靠一个富有活力的社区。现在是尝试 PyTorch 的好时机。

原文发布时间为:2017-10-01

本文作者:Illarion

本文来自合作伙伴“数据派THU”,了解相关信息可以关注“数据派THU”微信公众号

时间: 2024-10-30 13:45:41

手把手教你由TensorFlow上手PyTorch(附代码)的相关文章

机器学习零基础?手把手教你用TensorFlow搭建图像识别系统(三)| 干货

雷锋网按:本文是介绍用TensorFlow构建图像识别系统的第三部分. 在前两部分中,我们构建了一个softmax分类器来标记来自CIFAR-10数据集的图像,实现了约25-30%的精度. 因为有10个不同可能性的类别,所以我们预期的随机标记图像的精度为10%.25-30%的结果已经比随机标记的结果好多了,但仍有很大的改进空间.在这篇文章中,作者Wolfgang Beyer将介绍如何构建一个执行相同任务的神经网络.看看可以提高预测精度到多少!雷锋网(公众号:雷锋网)对全文进行编译,未经许可不得转

手把手教你使用TensorFlow生成对抗样本 | 附源码

更多深度文章,请关注:https://yq.aliyun.com/cloud 如果说卷积神经网络是昔日影帝的话,那么生成对抗已然成为深度学习研究领域中一颗新晋的耀眼新星,它将彻底地改变我们认知世界的方式.对抗学习训练为指导人工智能完成复杂任务提供了一个全新的思路,生成对抗图片能够非常轻松的愚弄之前训练好的分类器,因此如何利用生成对抗图片提高系统的鲁棒性是一个很有研究的热点问题. 神经网络合成的对抗样本很容易让人大吃一惊,这是因为对输入进行小巧精心制作的扰动就可能导致神经网络以任意选择的方式对输入

Android消息推送:手把手教你集成小米推送(附demo)_Android

前言 在Android开发中,消息推送功能的使用非常常见. 为了降低开发成本,使用第三方推送是现今较为流行的解决方案. 今天,我将手把手教大家如何在你的应用里集成小米推送 目录 1. 官方Demo解析 首先,我们先对小米官方的推送Demo进行解析. 请先到官网下载官方Demo和SDK说明文档 1.1 Demo概况 目录说明: DemoApplication类 继承自Application类,其作用主要是:设置App的ID & Key.注册推送服务 DemoMessageReceiver类 继承自

Android消息推送:手把手教你集成小米推送(附demo)

前言 在Android开发中,消息推送功能的使用非常常见. 为了降低开发成本,使用第三方推送是现今较为流行的解决方案. 今天,我将手把手教大家如何在你的应用里集成小米推送 目录 1. 官方Demo解析 首先,我们先对小米官方的推送Demo进行解析. 请先到官网下载官方Demo和SDK说明文档 1.1 Demo概况 目录说明: DemoApplication类 继承自Application类,其作用主要是:设置App的ID & Key.注册推送服务 DemoMessageReceiver类 继承自

手把手教你用 TensorFlow 实现卷积神经网络(附代码)

在知乎上看到一段介绍卷积神经网络的文章,感觉讲的特别直观明了,我整理了一下.首先介绍原理部分. 通过一个图像分类问题介绍卷积神经网络是如何工作的.下面是卷积神经网络判断一个图片是否包含"儿童"的过程,包括四个步骤: ● 图像输入(InputImage) ● 卷积(Convolution) ● 最大池化(MaxPooling) ● 全连接神经网络(Fully-ConnectedNeural Network)计算. 首先将图片分割成如下图的重叠的独立小块:下图中,这张照片被分割成了77张大

机器学习零基础?手把手教你用TensorFlow搭建图像识别系统(二)

这是Wolfgang Beyer一篇博文.详细介绍了如何使用TensorFlow搭建一个简单的图像识别系统.本篇将手把手地讲解搭建图像识别系统的全过程. 此系列文章主要介绍了不具备机器学习基础的用户如何尝试从零开始在TensorFlow上搭建一个图像识别系统.在文章的第一部分中,作者Woflgang Beyer向读者们介绍了一些简单的概念.本文为系列的第二部分,主要介绍了如何实现简单的图像识别功能.雷锋网编译,未经许可不得转载. 现在,我们可以开始建立我们的模型啦.实际上数值计算都是由Tenso

独家 | 10分钟带你上手TensorFlow实践(附代码)

这篇TensorFlow教程的目标读者是那些对机器学习有一定基本概念并且想尝试上手TensorFlow的人.首先你需要安装好TensorFlow(可以跟着本教程进行安装http://cv-tricks.com/artificial-intelligence/deep-learning/deep-learning-frameworks/tensorflow/install-tensorflow-1-0-gpu-ubuntu-14-04-aws-p2-xlarge/). 本教程共分为两部分: 第一部

手把手教你用 TensorFlow 实现文本分类(下)

本篇文章主要记录对之前用神经网络做文本识别的初步优化,进一步将准确率由原来的65%提高到80%,这里优化的几个方面包括: ● 随机打乱训练数据 ● 增加隐层,和验证集 ● 正则化 ● 对原数据进行PCA预处理 ● 调节训练参数(迭代次数,batch大小等)   随机化训练数据 观察训练数据集,发现训练集是按类别存储,读进内存后在仍然是按类别顺序存放.这样顺序取一部分作为验证集,很大程度上会减少一个类别的训练样本数,对该类别的预测准确率会有所下降.所以首先考虑打乱训练数据. 在已经向量化的训练数据

手把手教你用 TensorFlow 实现文本分类(上)

由于需要学习语音识别,期间接触了深度学习的算法.利用空闲时间,想用神经网络做一个文本分类的应用, 目的是从头到尾完成一次机器学习的应用,学习模型的优化方法,同时学会使用主流的深度学习框架(这里选择tensorflow). 文章分为两部分,本文仅实现流程,用简单的softmax回归对文本进行分类,后面一篇文章再从流程的各个方面对模型进行优化,达到比较好的效果.   收集数据 该部分不是这里的重点,数据从各大新闻网站爬取新闻文本,分十类保存到本地,包括科技.生活.体育.娱乐等.文本分别保存到trai