Pennod 06: Trosolwg o lyfrgelloedd gwyddonol

Yn symud ymlaen o Sympy, bydd y daflen lab yma yn rhoi trosolwg cryno ar nifer o lyfrgelloedd Python poblogaidd a all cael eu defnyddio i ddatrys nifer o broblemau gwahanol:

  • numpy cyfrifiadau rhifyddeg effeithlon (er enghraifft i wneud algebra llinol effeithlon);
  • matplotlib plotio;
  • scipy llyfrgell wyddonol cyffredinol (er enghraifft mae'n cynnwys algorithmau ar gyfer optimeiddio);
  • networkx theori graff/rhwydwaith (er enghraifft i gyfrifo rhif cromatig graff);
  • pandas triniaeth data (er enghraifft darllen data o ryw ffynhonnell a'i drin);
  • scikit-learn dysgu peiriannol (dyma un o lyfrgelloedd mwyaf poblogaidd Python).

Ni fydd y daflen lab yma yn rhoi trosolwg manwl o bob llyfrgell ond y nod yw rhoi cyflwyniad cryno o bob un.

Numpy - http://www.numpy.org/

Fideo yn disgrifio'r llyfrgell.

Llyfrgell sylfaenol ar gyfer gwneud cyfrifiadau effeithlon yw hyn. Y bloc adeiladu yma yw'r numpy.array a gall cael ei ddefnyddio ar gyfer triniaeth algebra llinol.

Gadewch i ni fewnforio numpy a diffinio dau fatrics 3 wrth 3:


In [1]:
import numpy as np
A = np.array([[5, 1, -1], [-1, 2, 4], [1, 1, 1]])
B = np.array([[1, 2, 0], [-4, 2, 2], [1, 3, 1]])

Gallwn gael mynediad i $A_{02}$ er enghraifft:


In [2]:
A[0, 2]


Out[2]:
-1

Neu rhes cyfan o $A$:


In [3]:
A[0]


Out[3]:
array([ 5,  1, -1])

Neu golofn gyfan:


In [4]:
A[:,1]


Out[4]:
array([1, 2, 1])

Gallwn gyflawni lluosi sgalar:


In [5]:
5 * A


Out[5]:
array([[25,  5, -5],
       [-5, 10, 20],
       [ 5,  5,  5]])

Gallwn godi'r matrics i bŵer uchel:


In [6]:
np.linalg.matrix_power(A, 5)


Out[6]:
array([[2357,  869,  211],
       [ -59,  290,  506],
       [ 599,  329,  231]])

Gallwn adio matricsau:


In [7]:
A + B


Out[7]:
array([[ 6,  3, -1],
       [-5,  4,  6],
       [ 2,  4,  2]])

A gallwn wneud pethau mwy cymhleth fel lluosi matricsau:


In [8]:
np.dot(A, B)


Out[8]:
array([[ 0,  9,  1],
       [-5, 14,  8],
       [-2,  7,  3]])

A gallwch gael gwrthdro a determinant $A$:


In [9]:
np.linalg.inv(A), np.linalg.det(A)


Out[9]:
(array([[ 1. ,  1. , -3. ],
        [-2.5, -3. ,  9.5],
        [ 1.5,  2. , -5.5]]), -2.0)

Mae hefyd gan Numpy nifer o ffwythiannau defnyddiol all fod yn ddefnyddiol hyd yn oed os nad ydyn yn gwneud algebra llinol. Er enghraifft gadewch i ni greu arae o 100 gwerth rhwng -2 ac 1:


In [10]:
np.linspace(-2, 1, 10 ** 2)


Out[10]:
array([-2.        , -1.96969697, -1.93939394, -1.90909091, -1.87878788,
       -1.84848485, -1.81818182, -1.78787879, -1.75757576, -1.72727273,
       -1.6969697 , -1.66666667, -1.63636364, -1.60606061, -1.57575758,
       -1.54545455, -1.51515152, -1.48484848, -1.45454545, -1.42424242,
       -1.39393939, -1.36363636, -1.33333333, -1.3030303 , -1.27272727,
       -1.24242424, -1.21212121, -1.18181818, -1.15151515, -1.12121212,
       -1.09090909, -1.06060606, -1.03030303, -1.        , -0.96969697,
       -0.93939394, -0.90909091, -0.87878788, -0.84848485, -0.81818182,
       -0.78787879, -0.75757576, -0.72727273, -0.6969697 , -0.66666667,
       -0.63636364, -0.60606061, -0.57575758, -0.54545455, -0.51515152,
       -0.48484848, -0.45454545, -0.42424242, -0.39393939, -0.36363636,
       -0.33333333, -0.3030303 , -0.27272727, -0.24242424, -0.21212121,
       -0.18181818, -0.15151515, -0.12121212, -0.09090909, -0.06060606,
       -0.03030303,  0.        ,  0.03030303,  0.06060606,  0.09090909,
        0.12121212,  0.15151515,  0.18181818,  0.21212121,  0.24242424,
        0.27272727,  0.3030303 ,  0.33333333,  0.36363636,  0.39393939,
        0.42424242,  0.45454545,  0.48484848,  0.51515152,  0.54545455,
        0.57575758,  0.60606061,  0.63636364,  0.66666667,  0.6969697 ,
        0.72727273,  0.75757576,  0.78787879,  0.81818182,  0.84848485,
        0.87878788,  0.90909091,  0.93939394,  0.96969697,  1.        ])

Matplotlib - https://matplotlib.org/

Fideo yn disgrifio'r llyfrgell.

Dyma'r llyfrgell fwyaf poblogaidd ar gyfer Python ar gyfer creu plotiau. Byddwn yn dangos hwn yn gyntaf trwy greu plot o'r ffwythiant:

$$ -x ^ 4 + 9x ^ 2 + 4 x - 12 $$

Rydym yn gwneud hwn trwy greu set o werthoedd $x$ a chyfrifo'r set gyfatebol o werthoedd $f(x)$:


In [11]:
def f(x):
    return - x ** 4 + 9 * x ** 2 + 4 * x - 12

xs = np.linspace(-4, 5, 10 ** 3)  # Creu 1000 o bwyntiau
ys = [f(x) for x in xs]

Nawr rydym yn barod i fewnforio a defnyddio matplotlib:


In [12]:
import matplotlib.pyplot as plt

%matplotlib inline

plt.figure()
plt.plot(xs, ys)
plt.xlabel("$x$")
plt.ylabel("$y$")
plt.show()


Nodwch fod y gorchymyn %matplotlib inline yn orchymyn arbennig i Jupyter sy'n sicrhâi y arddangosir plotiau yn y notebook hon.

Gallwn arbed y ddelwedd yma i ffeil i'w ddefnyddio rhywle arall:


In [13]:
plt.figure()
plt.plot(xs, ys)
plt.xlabel("$x$")
plt.ylabel("$y$")
plt.savefig("plot.pdf")   # arbrofwch gyda `.png`, `.jpg` ayyb...


Nodwch gallwn greu nifer o wahanol fathau o blotiau, er enghraifft dyma histogram o 1000 haprif a generadwyd gan numpy:


In [14]:
np.random.seed(0)  # Gosod hedyn
values = np.random.normal(size=10 ** 3)
plt.figure()
plt.hist(values, bins=20)
plt.xlabel("$Gwerth$")
plt.ylabel("Amledd")
plt.show()



Adnoddau pellach ar gyfer matplotlib

Scipy - https://docs.scipy.org/doc/scipy/reference/

Fideo yn disgrifio'r llyfrgell.

Llyfrgell yw Scipy sy'n casglu nifer o alluoedd gwahanol. Un peth gall e wneud yw canfod gwreiddiau trwy ddefnyddio technegau brasamcan rhifiadol:


In [15]:
from scipy import optimize

In [16]:
optimize.root(f, x0=0)


Out[16]:
    fjac: array([[-1.]])
     fun: array([0.])
 message: 'The solution converged.'
    nfev: 6
     qtf: array([4.84234874e-12])
       r: array([49.99999584])
  status: 1
 success: True
       x: array([3.])

In [17]:
f(3)


Out[17]:
0

Gall hefyd minimeiddio ffwythiannau (gyda mwy nag un newidyn):


In [18]:
def g(x):
    """Tybiwn fod g yn ffwythiant o 2 newidyn a bod x yn fector"""
    return np.cos(x[1]) / (1 + x[0])

In [19]:
optimize.minimize(g, x0=[0, 0])


Out[19]:
      fun: 0.002697614111595088
 hess_inv: array([[7.11535655e+06, 5.36889474e+00],
       [5.36889474e+00, 1.00000405e+00]])
      jac: array([-7.27712177e-06, -7.03148544e-07])
  message: 'Optimization terminated successfully.'
     nfev: 84
      nit: 20
     njev: 21
   status: 0
  success: True
        x: array([3.6969793e+02, 2.6064249e-04])

Gallwn hefyd ffitio ffwythiant i ddata, fan hyn byddwn yn creu data sy'n dilyn cromlin, ychwanegu bach o sŵn, a cheisio adfer y ffwythiant:


In [20]:
def ffwyth(x, a, b):
    return a * x ** 2 + b

xs = np.linspace(0, 10, 50)
gwerth_a, gwerth_b = 1 / 2, 70
np.random.seed(0)
ys = [ffwyth(x, a=gwerth_a, b=gwerth_b) + 2 * np.random.random() for x in xs]

Edrychwn ar y data:


In [21]:
plt.figure()
plt.scatter(xs, ys)
plt.show()



In [22]:
popt, pcov = optimize.curve_fit(ffwyth, xs, ys)

Adferwn ni'r gwerthoedd o a a b:


In [23]:
popt


Out[23]:
array([ 0.49563406, 71.22294657])

In [24]:
ys_ffitiwyd = [ffwyth(x, *popt) for x in xs]
plt.scatter(xs, ys, label="Data gwreiddiol")
plt.plot(xs, ys_ffitiwyd, label="Data a ffitiwyd", color="red")
plt.show()



Adnoddau pellach ar gyfer scipy

Networkx - https://networkx.github.io/

Fideo yn disgrifio'r llyfrgell.

Mae Networkx yn delio gyda gwrthrychau o theori graff. Gallwn greu graff mewn nifer o ffyrdd gwahanol, un o'r symlaf yw pasio set o ymylon. Fan hyn rydym yn mewnforio'r llyfrgell a chreu gwrthrych graff:


In [25]:
import networkx as nx
edges = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3)]
G = nx.Graph(edges)
G


Out[25]:
<networkx.classes.graph.Graph at 0x1013aa6dd8>

Mae'n bosib cael matrics cyfagosrwydd y graff:


In [26]:
M = nx.to_numpy_array(G)
M


Out[26]:
array([[0., 1., 1., 1.],
       [1., 0., 1., 1.],
       [1., 1., 0., 0.],
       [1., 1., 0., 0.]])

Mae hefyd yn bosib tynnu llun y graff:


In [27]:
plt.figure()
nx.draw(G)


Gallwch gyfrifo lliwio graff:


In [28]:
lliwio = nx.greedy_color(G)
lliwio


Out[28]:
{0: 0, 1: 1, 2: 2, 3: 2}

A gwelwn taw rhif cromatig y graff yw 3:


In [29]:
len(set(lliwio.values()))


Out[29]:
3

Pandas - https://pandas.pydata.org/

Fideo yn disgrifio'r llyfrgell.

Pandas yw brif lyfrgell Python ar gyfer trin data. Fel enghraifft byddwn yn ystyried set data at affêrau caru ar y slei: affairs.csv (download). Mae'r data yma o'r papur ymchwil canlynol:

Fair, Ray C. "A theory of extramarital affairs." Journal of Political Economy 86.1 (1978): 45-61.

Mae pdf ar gael fan hyn: https://fairmodel.econ.yale.edu/rayfair/pdf/1978A200.PDF

Gadewch i ni fewnforio pandas a darllen y set data:


In [30]:
import pandas as pd
df = pd.read_csv("affairs.csv")

Gallwn weld pen y set data:


In [31]:
df.head()


Out[31]:
sex age ym child religious education occupation rate nbaffairs
0 male 37.0 10.00 no 3 18 7 4 0
1 female 27.0 4.00 no 4 14 6 4 0
2 female 32.0 15.00 yes 1 12 1 4 0
3 male 57.0 15.00 yes 5 18 6 5 0
4 male 22.0 0.75 no 2 17 6 3 0

O'r papur gallwn ddarllen y newidynnau:

  • sex: Rhyw a adroddwyd yr unigolyn;
  • age: Oedran yr unigolyn;
  • ym: Nifer o flynyddoedd yn briod;
  • child: Os oes gan yr unigolyn plentyn;
  • religious: Pa mor grefyddol yw'r unigolyn (5: "iawn", 1: "dim");
  • education: Lefel addysg (9: ysgol gradd, 20: PhD neu MD);
  • occupation: Swydd yn seiliedig ar raddfa o'r enw "Hollingshead classification";
  • rate: Mesur yr unigolyn o'i briodas (5: "hapus iawn", 1: "anhapus iawn").

Gallwn gael trosolwg gloi o'r data gan ddefnyddio'r dull describe():


In [32]:
df.describe()


Out[32]:
age ym religious education occupation rate nbaffairs
count 601.000000 601.000000 601.000000 601.000000 601.000000 601.000000 601.000000
mean 32.487521 8.177696 3.116473 16.166389 4.194676 3.931780 1.455907
std 9.288762 5.571303 1.167509 2.402555 1.819443 1.103179 3.298758
min 17.500000 0.125000 1.000000 9.000000 1.000000 1.000000 0.000000
25% 27.000000 4.000000 2.000000 14.000000 3.000000 3.000000 0.000000
50% 32.000000 7.000000 3.000000 16.000000 5.000000 4.000000 0.000000
75% 37.000000 15.000000 4.000000 18.000000 6.000000 5.000000 0.000000
max 57.000000 15.000000 5.000000 20.000000 7.000000 5.000000 12.000000

Gallwn hefyd sleisio'r data mewn ffyrdd penodol, er enghraifft sut y mae'r rhif cymedrig o affêrau yn perthyn i fesur y briodas ac os yw'r unigolyn yn wryw neu’n fenyw?


In [33]:
df.groupby(["sex", "rate"])["nbaffairs"].mean()


Out[33]:
sex     rate
female  1       4.545455
        2       3.371429
        3       1.782609
        4       0.967742
        5       0.823077
male    1       2.400000
        2       4.548387
        3       1.085106
        4       1.623762
        5       0.588235
Name: nbaffairs, dtype: float64

Gallwn hefyd sleisio'r data gyda llaw, er enghraifft os hoffwn y data ar gyfer pobl wryw yn unig:


In [34]:
df[df["sex"] == "male"]


Out[34]:
sex age ym child religious education occupation rate nbaffairs
0 male 37.0 10.00 no 3 18 7 4 0
3 male 57.0 15.00 yes 5 18 6 5 0
4 male 22.0 0.75 no 2 17 6 3 0
7 male 57.0 15.00 yes 2 14 4 4 0
9 male 22.0 1.50 no 4 14 4 5 0
... ... ... ... ... ... ... ... ... ...
594 male 32.0 10.00 yes 4 14 4 3 3
595 male 47.0 15.00 yes 3 16 4 2 7
596 male 22.0 1.50 yes 1 12 2 5 1
598 male 32.0 10.00 yes 2 17 6 5 2
599 male 22.0 7.00 yes 3 18 6 2 2

286 rows × 9 columns

Gallwn gyfuno hwn gyda matplotlib er mwyn cael plot y rhif cymedrig o affêrau ar sail mesur priodas a rhyw:


In [35]:
plt.figure()
for sex in ["male", "female"]:
    plt.scatter(range(1, 5 + 1), df[df["sex"] == sex].groupby("rate")["nbaffairs"].mean(), label=sex)
plt.legend()
plt.xlabel("rate")
plt.ylabel("mean nbaffairs")
plt.show()


Adnoddau pellach ar gyfer pandas

Scikit-learn - http://scikit-learn.org

Fideo yn disgrifio'r llyfrgell.

Mae'r llyfrgell scikit learn yn llyfrgell boblogaidd ar gyfer dysgu peiriannau. Er enghraifft, gadewch i ni hyfforddi model a fydd yn rhagfynegi os bydd rhywun yn cael affêr gan ddefnyddio'r data uchod.

Yn gyntaf byddwn yn creu newidyn newydd o'r enw male a hefyd newid y newidyn child i fod yn boolean a storio'r data yma mewn ffrâm data newydd o'r enw X a fyddwn yn defnyddio i ragfynegi newidyn newydd arall o'r enw cheat (wedi'i storio yn y):


In [36]:
df["bool_child"] = df["child"] == "yes"
df["male"] = df["sex"] == "male"
X = df[["age", "ym", "religious", "education", "rate", "occupation", "bool_child", "male"]]
y = df["nbaffairs"] > 0

Nawr i fewnforio'r dosbarthydd penodol bydd yr algorithm yn defnyddio:


In [37]:
from sklearn.ensemble import RandomForestClassifier

In [38]:
seed = 3
clf = RandomForestClassifier(random_state=seed)
clf.fit(X, y)


/Users/vince/anaconda3/envs/cfm/lib/python3.6/site-packages/sklearn/ensemble/forest.py:246: FutureWarning: The default value of n_estimators will change from 10 in version 0.20 to 100 in 0.22.
  "10 in version 0.20 to 100 in 0.22.", FutureWarning)
Out[38]:
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
            max_depth=None, max_features='auto', max_leaf_nodes=None,
            min_impurity_decrease=0.0, min_impurity_split=None,
            min_samples_leaf=1, min_samples_split=2,
            min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=None,
            oob_score=False, random_state=3, verbose=0, warm_start=False)

In [39]:
for feature, importance in zip(X.columns, clf.feature_importances_):
    print(feature, round(importance, 5))


age 0.18605
ym 0.12635
religious 0.18442
education 0.16467
rate 0.13675
occupation 0.12495
bool_child 0.02848
male 0.04834

Y briodwedd fwyaf pwysig fan hyn yw oedran yr unigolyn. Gadewch i ni ddefnyddio ein model a hyfforddwn i ragfynegi os bydd rhyw unigolyn yn debygol o gael affêr dros ei fywyd:


In [40]:
oedrannau = range(35, 100)
tebygolrwydd_o_cael_affer = []
for oed in oedrannau:
    ym = oed - 24
    vince_knight = [[oed, ym, 1, 20, 5, 3, True, True]]
    tebygolrwydd_o_cael_affer.append(clf.predict_proba(vince_knight)[0][0])

plt.figure()    
plt.plot(oedrannau, tebygolrwydd_o_cael_affer)
plt.xlabel("Oedran Vince")
plt.ylabel("Tebygolrwydd Vince o cael affêr")
plt.ylim(0, 1)
plt.show()



Dyma drosolwg cryno o'r mathau o bethau gall pob llyfrgell eu gwneud, yn ddibynnau ar beth hoffwch wneud gwnewch yn siŵr o'u harchwilio'n llawn ac mae nifer o lyfrgelloedd arall yn yr ecosystem Python.