手把手教你学Numpy,从此处理数据不再慌「一」
当当当,我又开新坑了,这次的专题是Python机器学习中一个非常重要的工具包,也就是大名鼎鼎的numpy。
所以今天的文章是Numpy专题的第一篇。
俗话说得好,机器学习要想玩的溜,你可以不会写Python,但一定不能不会调库(大雾)。Numpy可以说是Python中最基础也是最重要的工具库了,要用Python做机器学习,玩转各种框架,Numpy是必须要会的。像是TensorFlow、pytorch这些知名框架都是基于Numpy进行计算的,可想而知它的重要性。
Numpy存在的必要性
网上关于Numpy的介绍非常多,但说来说去无非是一个Python中数值计算的非常重要的基础包,可以用来很方便地做一些矩阵和大数据的运算。
Numpy是做什么的我们很好理解,但是我们可能更加好奇它更深层次的意义究竟是什么?关于这个问题我们从浅到深不停地追问,可以得到许多不同的答案。
最浅层的回答很简单,Numpy很方便,计算速度快,可以很方便地进行矩阵运算。在Andrew的课程当中,他曾经演示过,同样的矩阵运算,如果我们通过Python中的循环实现速度会比调用Numpy慢上至少上百倍。这个差异显然是非常可怕的。
但为什么Numpy会更快呢?
我们追问下去,又会得到一个新的答案。因为Numpy包底层是通过C++实现的,显然C++运算比Python快得多,所以Numpy自然就更快了。
难道Numpy就只是因为C++更快这么简单吗?
这个问题已经超越了Numpy本身,我们需要从Python的特性来回答了。Python是一门解释型语言,也就是说当我们执行Python的时候,其实是执行了一个Python的解释器。由Python的解释器来解释执行Python的每一行代码。
如果我们把解释器理解成虚拟机,把Python执行的代码理解成虚拟机当中的程序。如果我们虚拟机多开的话,是很难保证线程安全的。为了解决这个问题,Python设计了GIL机制,也就是全局解释器锁,它保证了同一时刻最多只有一个解释器线程在执行。
这个机制保证了线程安全,但是也限制了Python多线程的使用。Python的多线程本质上是伪多线程,因为解释器只有一个线程在跑。所以如果我们想要通过多线程并发来加速计算的话,这是不可能的。
而矩阵和向量的一些操作是可以通过多线程并发来加速计算的,而Python本身的特性导致了Python不能执行这样的操作。那么通过Python调用C++实现的计算库也就是唯一的选择了。实际上不仅是Numpy,几乎所有Python的计算库,都是通过Python调用其他语言实现的。Python本身只是最上层的调用方。
理解了这点除了对于Python可以有更加清晰的认识之外,也有助于之后学习TensorFlow等其他框架。
Numpy中的n维数组
Numpy之所以好用,是因为我们可以通过Numpy很方便地创建高维的数组和矩阵。
举个例子,比如在原生Python当中,当我们需要创建一个二维数组的时候,往往需要些很长的定义。比如我们想要一个10 * 10的数组:
arr = [[0 for _ in range(10)] for _ in range(10)]
但是在Numpy当中就会很方便,只需要一行。
import numpy as np
arr = np.zeros((10, 10))
第一行当中我们引入了numpy,为了编码方便,我们将它重新命名成了np。这个是业内惯用做法,几乎所有使用numpy的程序员都会这么重命名。
在numpy当中,存储高维数组的对象叫做ndarray,与之对应的是存储矩阵的mat。其实这两者区别不大,支持矩阵的运算,ndarray基本上也都支持。我们有这么一个印象即可,关于mat内容我们会在之后介绍。
我们创建除了ndarray之后,关于获取ndarray基本信息的api大概有下面四个。
第一个是通过.ndim查看ndarray的维度,也就是查看这是一个几维的数组:
第二个是通过.shape获取这个ndarray在各个维度的大小:
第三个是通过.dtype获取这个ndarray中元素的类型:
最后一个是tolist()方法,可以将一个ndarray转化成Python原生的list进行返回。
ndarray
那么我们怎么创建numpy中的ndarray呢?
大概也有几种办法,首先,既然numpy中的ndarray可以转换成Python原生的list,同样Python中原生的list也可以转换成numpy中的ndarray。
和转换变量类型的语法很像,我们通过np.array()转换即可。
nums = [1, 3, 4, 6]
arr = np.array(nums)
除了通过Python中原生的list转换,我们还可以根据自己的需要创建新的ndarray。numpy创建array的方法有很多,我们先来介绍一下其中比较基础的几种。
创建出一个range
np.arange可以生成一个序列,有些类似于Python中原生的range。不过它更加灵活,我们可以之传入一个整数,它会返回一个从0开始的序列:
np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
我们也可以指定首尾元素和间隔,numpy会自动帮我们生成一个等差序列:
np.arange(1, 5, 0.5)
array([1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])
除此之外,numpy中还提供了ones和zeros两个api,可以生成全为0和全为1的元素。
np.zeros((3, 4))
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
np.ones((2, 3))
array([[1., 1., 1.],
[1., 1., 1.]])
我们还可以使用eye或者是identity生成一个N*N的单位矩阵:
np.eye(3)
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
除此之外,还有一个full的api可以指定shape和数值,用我们指定的数值填充出一个指定大小的数组来:
np.full((3, 4), 3)
array([[3, 3, 3, 3],
[3, 3, 3, 3],
[3, 3, 3, 3]])
但是这个api我们用的不多,因为我们可以用ones生成一个全为1的数组,然后乘上一个我们想要的值,就等价于full。
另外,ones, zeros, full这几个api还有一个对应的like方法。所谓的like方法就是我们传入另外一个ndarray代替shape,numpy会根据这个ndarray的形状生成一个对应形状的新array。
我们来看个例子吧,首先我们生成一个顺序的序列:
ex1 = np.arange(10)
然后我们通过zeros_like方法生成一个同样大小的全为0的矩阵:
ex2 = np.zeros_like(ex1)
它其实等价于:
np.zeros(ex1.shape)
其他几个like方法也大同小异,因为可替代性很强,所以我也用的不多。
numpy支持的类型
numpy支持的数据类型很多,除了常用的int和float之外,还支持复数类型的complex,某种程度上来说和golang支持的类型比较接近。
其中int类型一共分为int8,int32,int64和int128,其中每一种又分为带符号的和不带符号的。例如int8就是带符号的8位二进制表示的int,而uint8则是不带符号位的。浮点数没有无符号浮点数,一共分为float16,float32,float64和flaot128。
复数也有三种,分别是complex64,complex128和complex256。除此之外还有string_和object以及unicode_这三种类型。
我们可以通过调用astype方法更改ndarray中所有变量的类型:
ex1 = np.arange(10)
ex1.astype(np.float64)
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
除了人为转换之外,我们还可以在创建的时候通过dtype这个参数来表示我们想要创建的数据的类型,这样可以避免之后转换的麻烦。
ex1 = np.arange(10, dtype=np.float32)
结尾
这篇文章当中我们不仅介绍了Numpy的创建的方法,还聊了Python这门语言的一些特性。正是因为Python本身多线程的限制,导致它在需要高并发计算的场景下性能很差。才会需要通过Python去调用C++或者是其他语言的底层实现。这也是为什么Python经常被称为胶水语言的原因。
Numpy可以认为是Python进行机器学习的基础,当然除了Numpy之外,像是pandas、matplot以及scikit-learn等库也是必不可少的。我们会从Numpy开始,一点一点把这些常用的库都给大家分享一遍。
各位看官大人,喜欢的话,点个关注吧~
手把手教你学Numpy,从此处理数据不再慌「一」的更多相关文章
- 手把手教你学Numpy,搞定数据处理——收官篇
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Numpy专题第6篇文章,我们一起来看看Numpy库当中剩余的部分. 数组的持久化 在我们做机器学习模型的研究或者是学习的时候,在完成 ...
- 手把手教你学numpy,从此数据处理不再慌【三】
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是numpy专题的第三篇,我们来聊聊numpy当中的索引. 上篇的末尾其实我们简单地提到了索引,但是没有过多深入.没有过多深入的原因也很 ...
- 手把手教你学Numpy,这些api不容错过
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是Numpy专题的第5篇文章,我们来继续学习Numpy当中一些常用的数学和统计函数. 基本统计方法 在日常的工作当中,我们经常需要通过一 ...
- NN入门,手把手教你用Numpy手撕NN(三)
NN入门,手把手教你用Numpy手撕NN(3) 这是一篇包含极少数学的CNN入门文章 上篇文章中简单介绍了NN的反向传播,并利用反向传播实现了一个简单的NN,在这篇文章中将介绍一下CNN. CNN C ...
- 手把手教你学Dapr - 4. 服务调用
上一篇:手把手教你学Dapr - 3. 使用Dapr运行第一个.Net程序 介绍 通过使用服务调用,您的应用程序可以使用标准的gRPC或HTTP协议与其他应用程序可靠.安全地通信. 为什么不直接用Ht ...
- 手把手教你学Dapr - 5. 状态管理
上一篇:手把手教你学Dapr - 4. 服务调用 介绍 使用状态管理,您的应用程序可以将数据作为键/值对存储在支持的状态存储中. 您的应用程序可以使用 Dapr 的状态管理 API 使用状态存储组件来 ...
- 手把手教你学Dapr - 7. Actors
上一篇:手把手教你学Dapr - 6. 发布订阅 介绍 Actor模式将Actor描述为最低级别的"计算单元".换句话说,您在一个独立的单元(称为actor)中编写代码,该单元接收 ...
- 手把手教你学Dapr - 8. 绑定
目录 手把手教你学Dapr - 1. .Net开发者的大时代 手把手教你学Dapr - 2. 必须知道的概念 手把手教你学Dapr - 3. 使用Dapr运行第一个.Net程序 手把手教你学Dapr ...
- 手把手教你学Dapr - 9. 可观测性
目录 手把手教你学Dapr - 1. .Net开发者的大时代 手把手教你学Dapr - 2. 必须知道的概念 手把手教你学Dapr - 3. 使用Dapr运行第一个.Net程序 手把手教你学Dapr ...
随机推荐
- D - Yet Another Monster Killing Problem
题目连接: https://codeforces.com/contest/1257/problem/D 题目大意: n个怪兽,m个英雄,每个怪兽有一定的能力值,每个英雄有一定的能力值和一定的耐力值.耐 ...
- 2020新Asp.NET敏捷快速开发框架7.0.5旗舰版源码asp.net mvc框架,工具类CRM,工作流
演示地址: http://frame3.diytassel.com 用户名:system 密码:0000 需要的联系QQ:22539134 一.新添加了 1.多语言功能: 2.代码生成器模版 ...
- BUUOJ [CISCN2019 华北赛区 Day2 Web1]Hack World
补一下这道题,顺便发篇博客 不知道今年国赛是什么时候,菜鸡还是来刷刷题好了 0X01 考点 SQL注入.盲注.数字型 0X02自己尝试 尝试输入1 赵师傅需要女朋友吗???随便都能有好吧 输入2 ?? ...
- BIOS时间与系统时间(windows/linux时间同步问题)
写作动机 双系统是不少人喜欢的方式,但安装双系统之后一般会出现两个系统时间不一样的问题,刚开始用双系统的时候也没怎么在意,就是装上后在网上找找相关解决方法,复制粘贴代码完事儿.但是次数多了就有点烦了, ...
- 详解数组分段和最大值最小问题(最小m段和问题)
数组分段和最大值最小问题(最小m段和问题) 问题描述 给定n个整数组成的序列,现在要求将序列分割为m段,每段子序列中的数在原序列中连续排列.如何分割才能使这m段子序列的和的最大值达到最小? 清洁工:假 ...
- 编译原理-第四章 语法分析-4.6 简单LR技术
简单LR分析方法 一.LR语言分析器模型与算法 1.输入.输出.栈和方法 2.LR语法分析表 3.LR分析程序 4.例 例1: 例2: 二.LR语法分析算法 1.LR语法分析算法的定义和概念 定义: ...
- Web性能优化之-深入理解TCP Socket
什么是Socket? 大家都用电脑上网,当我们访问运维社区https://www.unixhot.com的时候,我们的电脑和运维社区的服务器就会创建一条Socket,我们称之为网络套接字.那么既 ...
- java.util.concurrent简介
文章目录 主要的组件 Executor ExecutorService ScheduledExecutorService Future CountDownLatch CyclicBarrier Sem ...
- Scala教程之:scala的参数
文章目录 默认参数值 命名参数 scala的参数有两大特点: 默认参数值 命名参数 默认参数值 在Scala中,可以给参数提供默认值,这样在调用的时候可以忽略这些具有默认值的参数. def log(m ...
- Java Web:jstl处理字符串
用法:${fn:methodName(args....)} 在使用这些函数之前必须在JSP中引入标准函数的声明<%@ taglib prefix="fn" uri=" ...