(記録) Python 機械学習 - Numpy 配列の高度な操作


序文

前 Numpy の基本

http://t.csdn.cn/eNkIt


1.スタッキング作業

stackスタッキングの意味はスタッキングの意味であり、いわゆるスタッキングとは、ndarray2つのオブジェクトを積み重ねて新しいndarrayオブジェクトを形成することです。重ねる方向によって、hstack2vstack種類に分けられます。

(1)hstack

特定の会社に所属している場合HR、その会社の従業員の基本的な情報を記録する必要があります。これまでに次の情報を記録している可能性があります。

ジョブ番号 名前 生年月日 連絡先番号
1 張三 1988.12 13323332333
2 李思 1987.2 15966666666
3 王武 1990.1 13777777777
4 土曜日 1996.4 13069699696

世界中で一定の需要があるわけではありません. 上司から、会社の全従業員の住所と戸籍登録住所を記録するように求められました. この時点で、これらの追加情報を記録する必要があります. 次に、次のようなものがあるかもしれません:

住宅アドレス 住所
江蘇省南京市禄口空港寮 202号室 江西省南昌市紅谷新区天越本土A棟2201号室
江蘇省南京市禄口空港寮 203号室 湖南省株州市天元区新天華府 11 号館 303 号室
江蘇省南京市禄口空港寮 204号室 四川省成都市武侯寺再定住コミュニティ 1 号館 701 号室
江蘇省南京市禄口空港寮 205号室 ルーム 1204、ビルディング B、Xingtian 家族、西湖区、杭州市、浙江省

次に、以前に記録した情報を、記録したばかりの追加情報と統合して、ソースに変換する必要があります。

ジョブ番号 名前 生年月日 連絡先番号 住宅アドレス 住所
1 張三 1988.12 13323332333 江蘇省南京市禄口空港寮 202号室 江西省南昌市紅谷新区天越本土A棟2201号室
2 李思 1987.2 15966666666 江蘇省南京市禄口空港寮 203号室 湖南省株州市天元区新天華府 11 号館 303 号室
3 王武 1990.1 13777777777 江蘇省南京市禄口空港寮 204号室 四川省成都市武侯寺再定住コミュニティ 1 号館 701 号室
4 土曜日 1996.4 13069699696 江蘇省南京市禄口空港寮 205号室 ルーム 1204、ビルディング B、Xingtian 家族、西湖区、杭州市、浙江省

統合すると、2 つのテーブル (2 次元配列) を水平方向に積み重ねて、それらを新しいテーブル (2 次元配列) に接合していることがわかります。このような振る舞いはhstack( horizontal stack)と呼ばれます。

NumPyhstack関数を実装する関数が提供されておりhstackhstack使用ルーチン コードは次のとおりです。

import numpy as np

a = np.array([[8, 8], [0, 0]])
b = np.array([[1, 8], [0, 4]])

'''
将a和b按元组中的顺序横向拼接
结果为:[[8, 8, 1, 8],
[0, 0, 0, 4]]
'''
print(np.hstack((a,b)))

c = np.array([[1, 2], [3, 4]])

'''
将a,b,c按元组中的顺序横向拼接
结果为:[[8, 8, 1, 8, 1, 2],
[0, 0, 0, 4, 3, 4]]
'''
print(np.hstack((a,b,c)))

(2)vstack

あなたはまだ特定の会社に所属しておりHR、その会社の従業員に関する情報を次のように記録しています。

ジョブ番号 名前 生年月日 連絡先番号
1 張三 1988.12 13323332333
2 李思 1987.2 15966666666
3 王武 1990.1 13777777777
4 土曜日 1996.4 13069699696

今日、2 人の新しい同僚が会社に加わりました。次のように、彼らの情報を記録する必要があります。

ジョブ番号 名前 生年月日 連絡先番号
5 リウ・チー 1986.5 13323332331
6 フ・バ 1997.3 15966696669

次に、新しく採用された同僚の情報を、すでに採用されている従業員の情報と統合する必要があります。

ジョブ番号 名前 生年月日 連絡先番号
1 張三 1988.12 13323332333
2 李思 1987.2 15966666666
3 王武 1990.1 13777777777
4 土曜日 1996.4 13069699696
5 リウ・チー 1986.5 13323332331
6 フ・バ 1997.3 15966696669

この場合、統合するときは、2 つのテーブル (2 次元配列) を垂直方向に積み重ねて、それらを新しいテーブル (2 次元配列) に接合します。このような振る舞いはvstack( vertical stack)と呼ばれます。

NumPyvstack関数を実装する関数が提供されておりvstackvstack使用ルーチン コードは次のとおりです。

    import numpy as np
    a = np.array([[8, 8], [0, 0]])
    b = np.array([[1, 8], [0, 4]])
    '''
    将a和b按元组中的顺序纵向拼接
    结果为:[[8, 8]
            [0, 0]
            [1, 8]
            [0, 4]]
    '''
    print(np.vstack((a,b)))
    c = np.array([[1, 2], [3, 4]])
    '''
    将a,b,c按元组中的顺序纵向拼接
    结果为:[[8 8]
            [0 0]
            [1 8]
            [0 4]
            [1 2]
            [3 4]]
    '''
    print(np.vstack((a,b,c)))

(3)やってみる

テスト ケース入力はディクショナリであり、feature1一部は function の内容を表しfeature1feature2一部は function の内容を表しますfeature2

テスト入力:{'feature1':[[1, 2, 3, 4], [4, 3, 2, 1], [2, 3, 4, 5]], 'feature2':[[1], [2], [3]]}

期待される出力:[2.33333333 2.66666667 3. 3.33333333 2. ]

import numpy as np


def get_mean(feature1, feature2):
    '''
    将feature1和feature2横向拼接,然后统计拼接后的ndarray中每列的均值
    :param feature1:待`hstack`的`ndarray`
    :param feature2:待`hstack`的`ndarray`
    :return:类型为`ndarray`,其中的值`hstack`后每列的均值
    '''
    #********* Begin *********#
    a=np.hstack((feature1,feature2))
    return np.mean(a, axis=0)#沿着a对象的0轴求均值
    #********* End *********#

2. 比較、マスキング、およびブール論理

(1) 比較する

ブーリアンマスクを使用して、配列内の値を表示および操作します。算術演算子と同様に、比較演算子はnumpyジェネリック関数で実装されます。比較演算子とそれに対応する汎用関数は次のとおりです。

比較演算子 ユニバーサル機能
== np.equal
!= np.not_equal
< np.less
<= np.less_equal
> np.greater
>= np.greater_equal

これらの比較演算子のジェネリック関数は、任意の形状とサイズの配列で使用できます。例は次のとおりです。

data=np.array([('Alice', 4, 40),('Bob', 11, 85.5),('Cathy', 7, 68.0),('Doug', 9, 60)],dtype=[("name","S10"),("age","int"),("score","float")]) #构造结构化数组


print(data["age"]<10)
'''
输出:array([ True, False, True, True])
'''

print(data["score"]>60)
'''
输出:array([False, True, True, False])
'''

print(data["score"]>=60)
'''
输出:array([False, True, True, True])
'''

print(data["score"]<=60)
'''
输出:array([ True, False, False, True])
'''

print(data["age"]!=9)
'''
输出:array([ True, True, True, False])
'''

print((data["age"]/2)==(np.sqrt(data["age"])))
'''
输出:array([ True, False, False, False])
'''

(2)マスクとしてのブール配列

より強力なパターンは、ブール配列をマスクとして使用して、データのサブデータセットを選択し、いくつかの操作を実行することです。

data=np.array([('Alice', 4, 40), ('Bob', 11, 85.5) ,('Cathy', 7, 68.0),('Doug', 9, 60)],dtype=[("name","S10"),("age","int"),("score","float")])

print(data)
'''
输出:[(b'Alice', 4, 40. )
(b'Bob', 11, 85.5)
(b'Cathy', 7, 68. )
(b'Doug', 9, 60. )]
'''


print(data["score"]>60) #使用比较运算得的一个布尔数组
'''
输出:[False True True False]
'''

print(data[data["score"]>60]) #进行简单的索引,即掩码操作将值为True的选出
'''
输出:[(b'Bob', 11, 85.5) (b'Cathy', 7, 68. )]
'''

(3)ブール論理

ビットごとの論理演算子と組み合わせて使用​​されますPython論理演算子に対応するnumpy一般的な関数は次のとおりです。

論理演算子 ユニバーサル機能
& np.bitwise_and
| | np.bitwise_or
^ np.bitwise_xor
np.bitwise_not
print(np.count_nonzero(data["age"]<10))#统计数组中True的个数
'''
输出:3
'''

#还可以用np.sum(),输出结果和count_nonzero一样,sum()的好处是可以沿着行或列进行求和
print(np.sum(data["age"]<10))

print(np.any(data["score"]<60))#是否有不及格的
'''
输出:True
'''

print(np.all(data["age"]>10))#是否都大于10岁
'''
输出:False
'''

print(data[data["age"]>10])#打印年龄大于10的信息
'''
输出:array([(b'Bob', 11, 85.5)],
dtype=[('name', 'S10'), ('age', '<i4'), ('score', '<f8')])
'''

(4)やってみる

テスト入力:[[ 3 ,15, 9 ,11 , 7],[ 2, 0 , 8, 19 ,16],[ 6 , 6, 16 , 9, 5],[ 7 , 5 , 2 , 6 ,13]] 10

期待される出力:[15 11 19 16 16 13]

import numpy as np


def student(num,input_data):
    result=[]
    # ********* Begin *********#

    result=np.array(input_data)#实例化数组
    result=result[result>num]#将数组中大于num的元素放入result的数组中

    # ********* End *********#
    return result


3. ファンシーインデックスとブールインデックス

(1)ファンシーインデックス

花式索引(Fancy Indexing)是NumPy用来描述使用整型数组(这里的数组,可以是NumPy的数组,也可以是python自带的list作为索引的术语,其意义是根据索引数组的值作为目标数组的某个轴的下标来取值。

使用一维整型数组作为索引,如果被索引数组(ndarray)是一维数组,那么索引的结果就是对应位置的元素;如果被索引数组(ndarray)是二维数组,那么就是对应下标的行。如下图所示:

示例代码如下:

import numpy as np

arr = np.array(['zero','one','two','three','four'])

'''
打印arr中索引为1和4的元素
结果为:['one', 'four']
'''
print(arr[[1,4]])

arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

'''
打印arr中索引为1和0的行
结果为:[[4, 5, 6],
[1, 2, 3]]
'''
print(arr[[1, 0]])

'''
打印arr中第2行第1列与第3行第2列的元素
结果为:[4, 8]
'''
print(arr[[1, 2], [0, 1]])

 (2)布尔索引

我们可以通过一个布尔数组来索引目标数组,以此找出与布尔数组中值为True的对应的目标数组中的数据,从而达到筛选出想要的数据的功能。如下图所示:PS:需要注意的是,布尔数组的长度必须与被索引数组对应的轴的长度一致)

我们可以想办法根据我们的需求,构造出布尔数组,然后再通过布尔索引来实现筛选数据的功能。

假设有公司员工绩效指数的数据如下(用一个一维的ndarray表示),现在想要把绩效指数大于3.5的筛选出来进行股权激励。

那首先就要构造出布尔数组,构造布尔数组很简单,performance > 3.5即可。此时会生成想要的布尔数组。

有了布尔数组就可以使用布尔索引来实现筛选数据的功能了。

示例代码如下:

import numpy as np

performance = np.array([3.25, 3.5, 3.75, 3.5, 3.25, 3.75])

'''
筛选出绩效高于3.5的数据
结果为:[3.75, 3.75]
'''
print(performance[performance > 3.5])

'''
筛选出绩效高于3.25并且低于4的数据
注意:&表示并且的意思,可以看成是and。&左右两边必须加上()
结果为:[3.5 3.75 3.5 3.75]
'''
print(performance[(performance > 3.25) & (performance < 4)])

(3)尝试

测试输入: ["d","a","A","p","b","I","C","K"]

预期输出: ['A' 'I' 'C' 'K']

import numpy as np

def student(input_data):
    result=[]
    #********* Begin *********#
    result=np.array(input_data)
    result=result[(result>='A') & (result<='Z')]#输出A~Z的字符

    # ********* End *********#
    return result

四、广播机制

(1)广播

当两个ndarray对象的形状并不相同的时候,我们可以通过扩展数组的方法来实现相加、相减、相乘等操作,这种机制叫做广播(broadcasting

比如,一个二维的ndarray对象减去列平均值,来对数组的每一列进行取均值化处理:

import numpy as np

# arr为4行3列的ndarray对象
arr = np.random.randn(4,3)
# arr_mean为有3个元素的一维ndarray对象
arr_mean = arr.mean(axis=0)
# 对arr的每一列进行
demeaned = arr - arr_mean

很明显上面代码中的arrarr_mean维度并不形同,但是它们可以进行相减操作,这就是通过广播机制来实现的。

(2)广播的原则

如果两个数组的后缘维度trailing dimension,即从末尾开始算起的维度)的轴长度相符,或其中的一方的长度为1,则认为它们是广播兼容的。广播会在缺失或长度为1的维度上进行,这句话是理解广播的核心。

广播主要发生在两种情况,一种是两个数组的维数不相等,但是它们的后缘维度的轴长相符,另外一种是有一方的长度为1

我们来看一个例子:

import numpy as np

arr1 = np.array([[0, 0, 0],[1, 1, 1],[2, 2, 2], [3, 3, 3]])
arr2 = np.array([1, 2, 3])
arr_sum = arr1 + arr2
print(arr_sum)

'''
输入结果如下:
[[1 2 3]
[2 3 4]
[3 4 5]
[4 5 6]]
'''

arr1shape(4,3)arr2shape(3,)。可以说前者是二维的,而后者是一维的。但是它们的后缘维度相等,arr1的第二维长度为3,和arr2的维度相同。

arr1arr2shape并不一样,但是它们可以执行相加操作,这就是通过广播完成的,在这个例子当中是将arr2沿着0轴进行扩展。

我们再看一个例子:

import numpy as np

arr1 = np.array([[0, 0, 0],[1, 1, 1],[2, 2, 2], [3, 3, 3]]) #arr1.shape = (4,3)
arr2 = np.array([[1],[2],[3],[4]]) #arr2.shape = (4, 1)

arr_sum = arr1 + arr2
print(arr_sum)

'''
输出结果如下:
[[1 1 1]
[3 3 3]
[5 5 5]
[7 7 7]]
'''

arr1shape(4,3)arr2shape(4,1),它们都是二维的,但是第二个数组在1轴上的长度为1,所以,可以在1轴上面进行广播。

(3)尝试

测试输入:

[[9, 3, 1], [7, 0, 6], [4, 6, 3]] [1, 5, 9] [[9], [6], [7]]

预期输出:

  1. [[19 17 19]
  2. [14 11 21]
  3. [12 18 19]]
import numpy as np

def student(a,b,c):
    result=[]
    # ********* Begin *********#

    a=np.array(a)
    b=np.array(b)
    c=np.array(c)
    result=a+b+c


    # ********* End *********#
    return result

五、线性代数

(1)numpy的线性代数

常用的numpy.linalg函数:

函数 说明
dot 矩阵乘法
vdot 2 つのベクトルの内積
行列式の計算
反対 正方行列の逆数を計算する
svd 特異値分解 (SVD) を計算する
解決 一次方程式系 Ax=b を解きます。A は正方行列です
マット 2 つの配列の行列積

1.ドット()

この関数は、2 つの配列の内積を返します。2 次元ベクトルの場合、効果は行列の乗算と同等です。1 次元配列の場合、これはベクトルの内積です。1 次元N配列の場合、a最後の軸と 2b番目の軸の合計の積です。の最後までの軸。(2 つの行列を乗算して、行と列を乗算します)

 

    a=np.array([[1,2],[3,4]])
    a1=np.array([[5,6],[7,8]])
    np.dot(a,a1)
    '''
    输出:array([[19, 22],
           [43, 50]])
    '''

2.それ()

入力行列の行列式を計算するために使用されます

    a = np.array([[14, 1], [6, 2]])
    a=linalg.det(a)
    print(a)
    '''
    输出:21.999999999999996
    '''

3.inv ()

正方行列の逆数を計算するために使用されます。逆行列の定義次元 2 つの正方行列AB、 の場合AB = BA = E、と の逆行列であるA可逆行列と呼ばれ恒等行列となります。BAE

a=np.array([[1,2],[3,4]])

b=linalg.inv(a)

print(np.dot(a,b))
'''
输出:array([[1.0000000e+00, 0.0000000e+00],
[8.8817842e-16, 1.0000000e+00]])
'''

4.解決する()

線形方程式の解を計算するために使用されます。

次の連立方程式を想定します3x+2y=7 x+4y=14

行列形式で記述: [[3,2][1,4]]* [[x],[y]]= [[7],[14]];

上記の方程式を解くコードは次のとおりです。

     a=np.array([[3,2], [1,4]])
     b=np.array([[7],[14]])
     linalg.solve(a,b)
    '''
     输出:array([[0. ],
           [3.5]])
     最后解出x=0,y=3.5
    '''

5.マットル()

2 つの配列の行列積を返します。引数に 1 次元配列がある場合、その次元に追加することによって行列に昇格され1、乗算後に減算されます。

    a=[[3,4],[5,6]]
    b=[[7,8],[9,10]]
    np.matmul(a,b)
    '''
    输出:array([[ 57,  64],
           [ 89, 100]])
    '''
    b=[7,8]
    np.matmul(a,b)
    '''
    输出:array([53, 83])
    '''

6.svd ()

特異値分解は、関数 を解くために使用される行列分解の方法ですSVD

    a=[[0,1],[1,1],[1,0]]
    linalg.svd(a)
    '''
    输出:(array([[-4.08248290e-01,  7.07106781e-01,  5.77350269e-01],
           [-8.16496581e-01,  2.64811510e-17, -5.77350269e-01],
           [-4.08248290e-01, -7.07106781e-01,  5.77350269e-01]]), array([1.73205081, 1.        ]), array([[-0.70710678, -0.70710678],
           [-0.70710678,  0.70710678]]))
    '''

(2)やってみる

テスト入力:

[["男",2,4,40],["女",8,3,17],["男",8,6,24]]

期待される出力:

  1. [[-7.2]
  2. [13.6]]
from numpy import linalg
import numpy as np
def student(input_data):
    '''
    将输入数据筛选性别为男,再进行线性方程求解
    :param input_data:类型为`list`的输入数据
    :return:类型为`ndarray`
    '''
    result=[]
    # ********* Begin *********#
    a=np.array(input_data)
    x=[]
    y=[]
    for i in a:#以数组a的长度来循环
        if i[0]=="男":#判断如果第一个元素是男"
            x.append([int(i[1]),int(i[2])])
            y.append([int(i[-1])])
    if x==[] and y==[]:
        return result
    x=np.array(x)
    y=np.array(y)
    result=linalg.solve(x,y)#解线性方程

    # ********* End *********#
    return result

おすすめ

転載: blog.csdn.net/qq_43659681/article/details/130178837