Skip to content

Latest commit

 

History

History
798 lines (541 loc) · 50.2 KB

File metadata and controls

798 lines (541 loc) · 50.2 KB

十六、高级应用计算思维问题

在本章中,我们将继续为 Python 编程语言和计算思维的应用提供多个领域的示例。我们将探索多个领域,例如几何细分、创建住房数据模型、创建电场、分析遗传数据、分析股票、创建卷积神经网络CNN)等等。我们将使用迄今为止所学的与计算思维Python编程语言相关的知识来完成以下工作:

  • 创建细分
  • 分析生物数据
  • 分析特定人群的数据
  • 创建住房数据模型
  • 创建电场线
  • 分析通用数据
  • 分析股票
  • 创建卷积神经网络(CNN)

阅读本章后,您将学习如何在使用数据时执行各种不同的分析,创建有助于分析现有数据的表格和图形,以及创建培训和测试模型,以帮助根据现有大型数据集预测结果。

技术要求

您需要安装最新版本的 Python 才能运行本章中的代码。

您需要为 Python 安装以下库和包:

  • NLTK
  • 凯洛斯
  • 熊猫
  • Matplotlib
  • Seaborn

您可以在此处找到本章中使用的完整源代码:https://github.com/PacktPublishing/Applied-Computational-Thinking-with-Python/tree/master/Chapter16

问题 1–使用 Python 创建细分

在本节中,我们将提供一个使用 Python 的cairo库的示例。我们将创建一个细分,更具体地说,是一个彭罗斯瓷砖的样本。因为这是一个简单的问题,我们将使用计算思维过程来定义我们的参数,但不严格遵守它。

首先,我们来谈谈cairo图书馆。一旦pip install cairo命令成功,您需要再执行一个步骤来包含所有需要的组件。使用pip install pycairo添加必要的组件。cairopycairo包是使用 Python 的图形库。有关更多信息,您可以访问他们的网页:https://cairographics.org/pycairo

现在让我们来定义一些东西。镶嵌是使用不重叠的形状来创建图案的瓷砖。几何课程中经常探索细分。对于我们的示例,我们将使用两个三角形创建 Penrose 平铺图案。我们还将定义我们的空间和我们希望形状经历的子划分的数量。子分区越多,定义的空间中的图案越小。让我们来看看算法(文件 HOLt0A.包含了下面讨论的全部算法:

  1. The first thing we'll do is import the necessary packages and libraries:

    ch16_tessellation.py

    import math
    import cmath
    import cairo
  2. 接下来,我们要定义画布和子分区的数量。请注意,我们选择了4作为示例。在图 16.1中,您将看到这个片段中的示例以及另外两个更改子划分的示例:

    #Define the configuration of the image. 
    canvas_size = (500, 500)
    numberSubdivisions = 4
  3. For the tessellation, we need to define the Golden Ratio.

    黄金比例也被称为黄金分割或神圣比例(除其他名称外)。比率约为 1.618。例如,如果我们讨论的是一条被分成两部分的线段,那么较大线段的长度除以较小线段的长度等于线段除以较大线段的总和:。对于镶嵌,我们需要定义黄金分割比率。

    请看以下代码段:

    #Define the Golden Ratio - gr
    gr = (1 + math.sqrt(5)) / 2
  4. Now we use functions to define what happens when our triangles sub-divide:

    def subdivide(triangles):
        result = []
        for color, A, B, C in triangles:
            if color == 0:
                P = A + (B - A) / gr
                result += [(0, C, P, B), (1, P, C, A)]
            else:
                Q = B + (A - B) / gr
                R = B + (C - B) / gr
                result += [(1, R, C, A), (1, Q, R, B), (0, R, Q, A)]
        return result

    在前面的代码中,我们定义了细分三角形的函数。该函数包含一个条件语句,用于在查找比率之前识别三角形的颜色。

  5. 要创建三角形的轮子,我们需要将三角形附加到组中。因为 Python 是一种面向对象的编程语言,所以我们可以通过创建一个空列表,然后使用循环添加形状来轻松实现这一点:

    #Wheel of teal triangles
    triangles = []
    for i in range(10):
        B = cmath.rect(1, (2*i - 1) * math.pi / 10)
        C = cmath.rect(1, (2*i + 1) * math.pi / 10)
        if i % 2 == 0:
            B, C = C, B  # Make sure to mirror every second triangle
        triangles.append((0, 0j, B, C))
    for i in range(numberSubdivisions):
        triangles = subdivide(triangles)
  6. 现在我们必须准备用于细分的画布。请注意,我们使用cairo函数来使用我们在算法开始时定义的变量来定义参数。在这里,我们使用canvas_size

    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, canvas_size[0], canvas_size[1])
    cr = cairo.Context(surface)
    cr.translate(canvas_size[0] / 2.0, canvas_size[1] / 2.0)
    wheelRadius = 1.2 * math.sqrt((canvas_size[0] / 2.0) ** 2 + (canvas_size[1] / 2.0) ** 2)
    cr.scale(wheelRadius, wheelRadius)
  7. Now we have to define the two triangles we'll be using. In this case, our triangles are teal and purple, but you can change the RGB values in them, that is, if you'd like to test different colors:

    #Define the teal triangles
    for color, A, B, C in triangles:
        if color == 0:
            cr.move_to(A.real, A.imag)
            cr.line_to(B.real, B.imag)
            cr.line_to(C.real, C.imag)
            cr.close_path()
    cr.set_source_rgb(.2, .8, .8)
    cr.fill()    
    #Define the purple triangles
    for color, A, B, C in triangles:
        if color == 1:
            cr.move_to(A.real, A.imag)
            cr.line_to(B.real, B.imag)
            cr.line_to(C.real, C.imag)
            cr.close_path()
    cr.set_source_rgb(0.7, 0, 0.7)
    cr.fill()
    color, A, B, C = triangles[0]
    cr.set_line_width(abs(B - A) / 10.0)
    cr.set_line_join(cairo.LINE_JOIN_ROUND)

    前面的代码创建了蓝绿色三角形和紫色三角形。每个都使用 RGB 值定义,并使用路径和线创建。

  8. 旋转的三角形形成平铺图案,即我们的细分。瓷砖也用边框隔开。边框的颜色也在下面的循环中定义:

    #Triangle borders
    for color, A, B, C in triangles:
        cr.move_to(C.real, C.imag)
        cr.line_to(A.real, A.imag)
        cr.line_to(B.real, B.imag)
    cr.set_source_rgb(0.3, 0.5, 0.3)
    cr.stroke()
  9. Finally, we want the algorithm to create an image file with our tessellation:

    surface.write_to_png('tessellation.png')

    以下屏幕截图显示了我们的算法使用不同数量的子分区的三种变化:

Figure 16.1 – Sample tessellations

图 16.1–示例镶嵌

正如您从前面的图像中看到的,子分区的数量越大,瓷砖图案就越小,以适合我们定义的画布大小。

当你玩算法时,考虑改变画布大小、子分区和颜色。如果您需要额外的挑战,请尝试将三角形图案更改为另一个多边形。

问题 2–在生物数据分析中使用 Python

对于这个特定的问题,我们将使用文件,该文件可以在Kaggle上找到 https://www.kaggle.com/nsaravana/breast-cancer?select=breast-cancer.csv)。该文件也已上载到该书的 GitHub 存储库。

在查看数据时,有时我们希望与我们目前拥有的数据进行比较,或者我们希望将其用于机器学习中的预测。在本例中,我们将研究如何使用数据集中的两个特定列值来表示另一种类型的图,即散点图

假设您收到了这些数据,并且已经确定您的平均周长和平均纹理比列中的其他值更好预测值。您现在的目标是创建一个算法,通过使用散点图比较这两列的值来分析这两列的值。我们的目标只是得到那个散点图。对于其他分析和机器学习应用程序,可以自由探索第 13 章使用分类和聚类第 14 章在统计分析中使用计算思维和 Python,需要更多帮助。

此问题的完整代码可在文件ch16_BreastCancerSample.py中找到。我们现在可以开始设计我们的算法:

  1. 我们从通常处理数据开始,导入我们将使用的库。注意,我们在这里使用两个显示库,matplotlibseaborn库。这是我们第一次使用seaborn。我们使用seaborn是因为额外的工作,例如寻找回归线,在这个库的帮助下很容易处理:

    #Import libraries needed
    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    %matplotlib inline
  2. Now we're going to find the .csv file. Remember that you can always establish the directory first. Otherwise, make sure you include the full location of the file. Since our directories are different, make sure you change that before running the file:

    #Get data set. Remember to check your directory and/or add the full location of the file.
    dataset = pd.read_csv('C:\\... \\breast-cancer.csv')
    dataset.head()
    dataset.isnull().sum()

    注意算法中的dataset.head()命令。如果我们只运行代码到该点,则会得到以下输出:

    Figure 16.2 – Table showing the heading values

    图 16.2–显示标题值的表格

    dataset.isnull().sum()命令帮助我们查看是否有空数据点或值。

  3. If we have many null points, we can clean the dataset before we start the analysis. This data is clean, as can be seen from the following output if we run the program up until dataset.isnull().sum(), as can be seen in the following screenshot:

    Figure 16.3 – Output of the null check

    图 16.3–空检查的输出

  4. Since there are no missing values, as seen in the preceding screenshot, we're going to continue to our next snippet, where we'll create the count variable for diagnosis:

    #Create count variable for diagnosis
    count = dataset.diagnosis.value_counts()
    count

    count变量是在前面的代码片段中创建的,这意味着我们可以使用诊断值创建条形图,无论诊断是恶性还是良性。

  5. The following code snippet creates that bar graph and shows us the resulting output:

    #Create bargraph of the diagnosis values
    count.plot(kind = 'bar')
    plt.title('Tumor distribution (malignant: 1, benign: 0)')
    plt.xlabel('Diagnosis')
    plt.ylabel('count')
    plt.show()

    查看以下屏幕截图,其中显示了使用诊断值的条形图。如您所见,条形图显示了恶性肿瘤与良性肿瘤的计数:

    Figure 16.4 – Malignant versus benign diagnosis bar graph

    图 16.4–恶性与良性诊断条形图

    现在我们有了这些信息和条形图,我们可以开始使用数据集中的值来查看其他组合和比较。

  6. You can run a different analysis to see which are more relevant, but for now, we are just going to use the perimeter mean and texture mean to create our scatterplot. The following code snippet shows how to create those using the seaborn library:

    y_target = dataset['diagnosis']
    dataset.columns.values
    dataset['target'] = dataset['diagnosis'].map({0:'B',1:'M'})
    #Create scatterplot of mean perimeter and mean texture
    sns.scatterplot(x = 'perimeter_mean', y = 'texture_mean', data = dataset, hue = 'diagnosis', palette = 'bright');

    创建散点图后,算法将返回以下输出,显示与平均纹理散点图相比的平均周长散点图:

Figure 16.5 – Mean perimeter versus mean texture scatterplot

图 16.5-平均周长与平均纹理散点图

我们将在这里暂停此数据分析。但是,请注意,您可以进一步了解这个示例。事实上,你可以在 Kaggle 中找到多个应用程序和使用这个特定数据集进行的分析,以及一些开发人员和编码人员如何结合机器学习来进行预测。生物信息学的世界是广阔的,数据科学的应用正在继续增长。在这些问题中使用 Python 是很有帮助的,因为 Python 易于使用并且具有适用的库。

问题 3–使用 Python 分析特定人群的数据

在本节中,我们将以这种方式陈述我们的问题,即 2020 年,由于SARS-COV-19病毒,也被称为冠状病毒COVID-19而导致的大流行使世界不堪重负。这些数据是广泛可得的,我们正试图了解某一特定地点发生的情况,特别是该地点的死亡人数是如何增长的。我们找到纽约时报 GitHub 存储库,其中包含新冠病毒-19 数据,并下载每日更新的主数据。让我们看看我们需要做什么以及如何找到它。

定义具体问题,以分析和识别人群

这个问题很广泛。*太宽了!*我们先看一个地点,只看一个月。例如,让我们选择波多黎各和十月。从主.csv文件中,我们只提取了波多黎各特定的数据,并将其添加到我们的存储库中。同样,可以在《纽约时报》的 covid-19-data 存储库中找到主数据,您可以使用完整数据、特定州甚至特定县执行多个分析。

现在,我们将集中精力为 2020 年 10 月波多黎各特定的死亡数据创建一个可视化。仅从数据来看,我们看到死亡人数正在上升。请看以下屏幕截图:

Figure 16.6 – Data for the first 20 days of October 2020 in Puerto Rico

图 16.6–波多黎各 2020 年 10 月前 20 天的数据

正如您从前面的屏幕截图中看到的,死亡一栏继续上升,病例数量也在上升,我们稍后将在这个问题中关注这一点。

虽然以表格形式读取的数据可能会有所帮助,但如果我们要呈现这些信息,尤其是如果我们想确定趋势并影响政策变化,则视觉表示至关重要。让我们来看看我们如何为这个特定的数据创建散点图。完整文件可在ch16_CovidPR.py中找到:

  1. 与处理数据时一样,我们需要确保导入将要使用的库:

    import pandas as pd
    import matplotlib.pyplot as plt
  2. 下一步,我们需要得到我们的文件。记住,有多种方法可以做到这一点。您可以向 Python 提供文件的完整位置,也可以首先确定目录,只提供文件名。请确保在运行程序之前更改要使用的.csv文件的位置:

    df = pd.read_csv('C:\\...\\us-PuertoRico.csv')
  3. After identifying the file, we'll just create a simple scatterplot using the dates as our x-axis, and the deaths as our y-axis. The next few commands in this code snippet are done to make it easier to read the chart, such as the y-axis label, the rotation of the x-tick marks, and the title of the chart. The x-tick marks are the division marks for the horizontal axis, or x-axis. You can see the x-tick marks and the labels in Figure 16.6:

    plt.scatter(df['date'], df['deaths'])
    plt.xticks(rotation = 90)
    plt.title('Deaths per day during October 2020 due to COVID19 in Puerto Rico')
    plt.ylabel('Number of Deaths')
    fig.tight_layout()
    plt.show()
    plt.savefig('COVID_PR.png')

    正如您从前面的代码片段中所看到的,我们还创建了一个图像文件,以便在需要时稍后使用。该图表将显示在我们的屏幕上,如以下屏幕截图所示:

Figure 16.7 – Deaths per day during October 2020 due to COVID-19 in Puerto Rico

图 16.7-2020 年 10 月波多黎各因新冠病毒-19 导致的每日死亡人数

这是一张有用的图表,可以看出死亡人数正以稳定的速度增长。我们可以做更多的事情,比如尝试确定回归,这是我们可以使用numpy库使用 Python 实现的另一个功能,欢迎您使用!

现在,我们将按日期查看这些案例。代码与前面相同,只是我们的y轴和标题不同。完整代码可在ch16_CovidPR_2文件中找到。由于代码非常相似,我们不在这里共享它。但是,我们的结果图可以在以下屏幕截图中看到:

Figure 16.8 – Cases per day during October 2020 due to COVID-19 in Puerto Rico

图 16.8-2020 年 10 月波多黎各每天因新冠病毒-19 感染的病例

从前面的截图中可以看出,波多黎各的病例数量每天都在增加。我们可以用这两张图做很多事情;分析他们的回归,通过查看其他月度数据来验证其他趋势,等等。现在,您已经了解了如何创建一个简单的绘图来显示基于.csv文件的数据;剩下的就看你了。我们将在下一节中研究一个新问题。

问题 4–使用 Python 创建住房数据模型

让我们来看看损坏的问题,我们想展示纽约布鲁克林区的住宅市场的趋势和信息。数据集包括 2003-2017 年纽约市住房销售数据中的信息。使用的数据集以可用格式合并了信息,可在 Kaggle 上找到(https://www.kaggle.com/tianhwu/brooklynhomes2003to2017 )。此外,可以在 GitHub 存储库中找到名为brooklyn_sales_map.csv.csv文件副本。

定义问题

对于这个特殊问题,我们有一个大数据文件。我们可以按邻居查看信息,按年份查看销售价格,将建成年份与邻居进行比较,以发现趋势、历史等。我们可以在这一数据集上花费数小时、数天和周的时间。因此,让我们试着把我们的精力集中在这个例子中我们将要完成的事情上。为此,我们将创建两个视觉模型。第一个是根据销售年份,销售范围内住房百分比的水平条形图。第二个是条形图,显示了出售房屋的街区的价格范围。

水平条形图有助于以更清晰的方式显示数据,以便我们可以看到房价范围以及是否有重大变化。垂直条形图可以显示每个街区的相同价格范围,因此我们可以根据出售房屋的街区看到是否有显著变化。

算法与数据的可视化表示

让我们看一下 Type T1 代码片段。完整文件可在 GitHub 存储库中的ch16_housingBrooklyn.py下找到。与往常一样,在尝试运行程序之前,不要忘记更新文件中的文件位置:

  1. 对于这个特定的程序,我们需要pandasmatplotlib库,所以我们需要导入它们:

    import pandas as pd
    import matplotlib.pyplot as plt
  2. 接下来,我们需要读取我们的文件。这是您需要更新此代码的地方,以便从您的计算机上运行它:

    df = pd.read_csv('C:\\...\\brooklyn_sales_map.csv')
  3. 现在我们要创建我们的bins。这些是我们的值范围,我们将在创建图表时调用它们,正如您在下面几行代码的df['price_range']下所看到的:

    bins = [-100000000,20000,40000,60000,80000,100000,1000000,10000000,500000000]
    ranges_prices = ['$0-$200k','$200k-$400k','$400k-$600k','$600k-$800k','$800k-$1mlln','$1mlln-$10mlln','$10mlln-$100mlln','$100mlln-$500mlln']
    df['price_range'] = pd.cut(df['sale_price'], bins = bins, labels = ranges_prices)
  4. Now we're going to define a function, where we are going to convert some of the data. Notice that we run that function on each of the years from the dataset to find our percent total, which we'll use later on for housing_df:

    def convert(year):
        return df[df['year_of_sale'] == year].groupby('price_range').size()
    percent_total = [x/sum(x)*100 for x in [convert(2003),convert(2004),convert(2005),convert(2006),convert(2007),convert(2008),convert(2009),convert(2010),convert(2011),convert(2012),convert(2013),convert(2014),convert(2015),convert(2016),convert(2017)]]
    year_names = list(range(2003,2018))
    housing_df = pd.DataFrame(percent_total, index = year_names)
    ax_two = housing_df.plot(kind = 'barh', stacked = True, width = 0.9, cmap = 'Spectral')
    plt.legend(bbox_to_anchor = (1.45, 1), loc='upper right')
    ax_two.set_xlabel('Percentages', fontname='Arial', fontsize = 12)
    ax_two.set_ylabel('Years', fontname='Arial', fontsize = 12)
    ax_two.set_title('Housing Sale ')

    前面的代码片段帮助我们创建两个模型中的第一个。这是一个水平条形图。我们标记了所有轴和图形,然后,在前面代码片段中显示的下一行中,我们还定义了用于此图形的颜色映射,在本例中为'Spectral'。为了便于阅读,您可以使用可用的颜色映射。请看我们的第一个图表,如下所示:

    Figure 16.9 – Housing sales in Brooklyn by year

    图 16.9——布鲁克林按年份划分的房屋销售

    请注意,我们在前面的屏幕截图中使用了百分比。这使我们能够显示每个价格范围内的销售额,但不能显示每个价格范围内的实际销售额。这两件事完全不同。在这里,我们正在寻找趋势。在从20082009略有下降后,销售额高于 1000000 美元的百分比一直在上升。2017 年的销售额高于该价格点的比例远高于 2003 年

    但那是总销售额。如果我们只看这张图表而不看数字,我们就不知道 2017 年的房屋销售总量是否会减少,比如。再次强调,这里需要注意的重要一点是,这个图表对于理解每个价格范围下的房屋销售份额非常有帮助,但这就是这个图表真正提供给我们的。现在让我们看一下文件中的剩余代码。

  5. In this next snippet, we create our second graph, which uses our information to produce a vertical bar graph with the percentages within each price range for each neighborhood:

    df.groupby(['neighborhood','price_range']).size().unstack().plot.bar(stacked = True, cmap = 'rainbow')
    plt.legend(bbox_to_anchor = (1.45, 1), loc = 'upper right')
    plt.title('Pricing by Neighborhoods in Brooklyn from 2003 to 2017')
    plt.ylabel('Price Range')
    plt.xticks(fontsize = 6)

    这张图用条形图向我们展示了每个街区的价格范围。让我们看看下面截图中的第二张图:

Figure 16.10 – Pricing by neighborhoods in Brooklyn from 2003-2017

图 16.10——2003-2017 年布鲁克林各社区的定价

正如您从前面的屏幕截图中所看到的,我们得到了一些重要信息,这些信息比图 16.1中的信息更多或更详细。在这种情况下,数据按社区提供,细分按这些社区的价格范围提供。

当我们查看一个大型数据集时,我们可以创建多个不同的模型,甚至可以使用它们预测未来的值。查看.csv文件中的可用数据,并尝试使用其他数据创建一些不同的表示形式,例如商业与住宅销售、税收类别细分等。

问题 5–使用 Python 创建电场线

在本节中,让我们看一下 Python 在工程中的一些应用,特别是在物理方面。我们将创建电场线图。*我们为什么要创造这样的情节?它到底是什么?*当有电荷时,就会产生电场。我们用矢量来表示空间中每个点的电场。在物理学中,电场是每单位电荷的一种电力。看看正极点电荷和负极点电荷的场是什么样子,如下图所示:

Figure 16.11 – Electric field sample

图 16.11–电场样本

如你所见,电场线将从电荷开始,或在电荷结束。如果它从充电开始,它是正的,而如果它在充电结束,它是负的,如前面的屏幕截图所示。较小电荷的线数较少,较大电荷的线数较多。此外,与较小的电荷相比,较大电荷的线更近。

对于我们的问题,我们想为任意数量的电荷创建一个电场线图。让我们看看下面的代码文件中会是什么样子。请注意,我们已经对代码进行了分解以解释各个部分,但是可以在 GitHub 存储库中找到完整的文件:

  1. As usual, first, we'll begin by importing the necessary libraries:

    ch16_ 电场线.py

    import numpy as np
    import matplotlib.pyplot as plt
    import random
  2. Then, we'll set up our x and y axes by defining some variables:

    np.seterr(divide='ignore', invalid='ignore')
    #Define the size of the electric field lines grid
    N = 20
    M = 25
    #Set the x and y coordinates
    x_coor = np.arange(0, M, 1)
    y_coor = np.arange(0, N, 1)
    x_coor, y_coor = np.meshgrid(x_coor, y_coor)
    E_x = np.zeros((N, M))
    E_y = np.zeros((N, M))

    在前面的代码片段中,我们致力于定义网格并设置坐标。然后我们创建网格。meshgrid()函数从矢量坐标返回坐标矩阵。

  3. After we have set our coordinates and set our mesh grid, we can start defining what happens with our charges. First, we'll need to identify how many charges will be plotted:

    #Set the number of total charges to plot
    nq = 8
    #Create empty lists to store coordinates of charges
    qq = [[], []]  
    for dummy in range(nq): 
        q = random.choice([-1, 1])
        q_x, q_y = random.randrange(1, N), random.randrange(1, M)
        qq[0].append(q_y)
        qq[1].append(q_x)
        for i in range(N):
            for j in range(M):
                denom = ((i - q_x) ** 2 + (j - q_y) ** 2) ** 1.5
                if denom != 0: 
                    E_x[i, j] += q * (j - q_y) / denom
                    E_y[i, j] += q * (i - q_x) / denom

    正如您从前面的代码片段中所看到的,在我们确定了费用数量之后,我们创建了两个空列表。然后,我们使用嵌套的for循环,根据电荷数向这些列表添加坐标。

  4. After we do the necessary math to get our coordinates and vectors, we can then go ahead and plot our electric field lines graph. We'll use a quiver plot, which is a matplotlib graphic we can use for creating vector fields:

    C = np.hypot(E_x, E_y)
    E = (E_x ** 2 + E_y ** 2) ** .5
    E_x = E_x / E
    E_y = E_y / E
    plt.figure(figsize=(12, 8))
    #Plot charges
    plt.plot(*qq, 'ms')
    #Create 2D array
    rr = plt.quiver(x_coor, y_coor, E_x, E_y, C, pivot='middle')
    cbar = plt.colorbar()
    cbar.ax.set_ylabel('Magnitude')
    #Label graph
    plt.title('Electric Field Lines in Python')
    plt.axis('equal')
    plt.axis('off')
    plt.show()

    始终在图形和绘图中添加标签非常重要,因为这将使信息更具可读性,特别是对于那些不知道这背后的代码是什么意思或图形和绘图代表什么的人。当我们运行代码段时,我们得到以下输出:

    Figure 16.12 – Electric field lines for eight charges

    图 16.12–八种电荷的电场线

    正如你在图中看到的,有正电荷和负电荷。看看图中右下角的角电荷。该电荷为负电荷,因为箭头指向该电荷。最左边的电荷已放大,如下所示,显示正电荷,箭头指向远离电荷的方向:

    Figure 16.13 – Zoomed positive charge

    图 16.13–缩放正电荷

  5. 让我们看一个最后的图形,在下面的截图中显示,有三个电荷的电场线图:

Figure 16.14 – Electric field lines with three charges

图 16.14–带三个电荷的电场线

正如你所看到的,这个特殊的图包含两个正电荷和一个负电荷。如果我们再次运行这个,我们可能会得到三个正电荷,例如,当我们每次运行这个算法时,我们会得到一个新的表示形式,带有正负电荷的随机值。

这些类型的字段和学习如何使用向量和颤动图可以帮助我们表示很多信息。在电场线的情况下,我们可以通过一个简单的可视化绘图了解很多关于电荷、方向和电荷强度的信息。

查看 GitHub 存储库中的代码片段,并尝试更改一些参数,例如绘图的大小和费用的数量。通过这些绘图和修改某些参数进行的练习越多,它们就越容易创建。

问题 6–使用 Python 分析遗传数据

让我们把注意力转移到更大的数据集上。您正在与实验室小鼠合作,获取三体小鼠和这些小鼠中蛋白质表达的数据。由于 Kaggle 中的公共域文件太大,因此我们截断了其中的一些数据。我们只关注六只蛋白在小鼠中的表达,同样,研究中只关注三体(唐氏综合征小鼠)。完整文件可在的 Kaggle 中找到 https://www.kaggle.com/ruslankl/mice-protein-expression 。截断的文件可以在我们的 GitHub 存储库中找到。

假设您不知道从何处开始使用这些数据。*你应该看什么?*这通常是我们在数据科学中遇到的第一件事。我们并不总是参与研究设计或数据收集。很多时候,我们会收到大量数据文件,需要弄清楚要查找什么,如何解决问题,无论我们决定问题是什么,以及如何以最佳方式显示信息。

此外,这是您在尝试运行此程序之前更改文件位置的提示。这个非常简单的程序可以在ch16_pairplots.py文件中找到。让我们从算法开始:

  1. The seaborn library can help us a bit just to get us started. We can create pairplot(), which will correlate the numerical data in the .csv file using histograms and scatterplots. It's kind of like a fantastic magic trick. We can use two lines of code to see what we see. Take a look at the two lines that are needed to generate Figure 16.7 (note that there's actually four lines of code, but I'm not counting the two lines I'm using to import my libraries):

    import seaborn as sns
    import pandas as pd
    df = pd.read_csv('C:\\...\\Data_Cortex_Nuclear.csv')
    sns.pairplot(df, hue = 'Treatment')

    运行此程序时请耐心。算法可能很简单,但它在后台做的事情并不简单。请查看以下屏幕截图以查看我们的 pairplot:

    Figure 16.15 – Pairplot of protein expressions in trisomy mice with the treatment variable

    图 16.15–具有治疗变量的三体小鼠的成对蛋白质表达

    注意,我们的数据有两种基于治疗的颜色,分别是注射美金刚或生理盐水。从图中,我们可以看到一些蛋白质似乎比其他蛋白质具有更高的相关性。让我们暂停一下。

  2. 现在让我们说,我们的目标不是检查基于治疗的表达式,而是检查类。然后我们可以运行代码,但首先我们在算法中将色调更改为class。结果如下所示:

Figure 16.16 - Pairplot of protein expressions in trisomy mice with the class variable

图 16.16-具有类变量的三体小鼠中的成对蛋白质表达

请注意,图非常相似。然而,图的不同之处在于基于另一个特征确定每个点的位置。例如,在class变量图表中,我们有四种颜色,因为在我们的特定数据集中有四类鼠标。

t-CS-s,是指受刺激学习(休克)并注射生理盐水的小鼠;t-CS-m,指刺激学习(休克)并注射美金刚的小鼠;t-SC-s,指不刺激学习的小鼠,注射生理盐水;t-SC-m,指不刺激学习的小鼠,注射美金刚。

从我们的相关性来看,我们可以看到许多蛋白质之间存在很强的正相关性,例如NR2A_NBDNF_N。如果这是我们的研究,我们必须考虑这是否相关,在我们的研究中是否重要,是否不重要。一旦我们看到了这些情节,我们就可以选择进一步探索这些信息。

当查看此数据集时,可能有帮助的另一种类型的图是箱线图。我们可以使用箱线图来查看我们想要更仔细观察的蛋白质的蛋白质表达水平。我们来看看NR2A_N蛋白质。使用seaborn箱线图,我们可以使用ch16_boxplot.py文件中的代码为这个特定的蛋白质创建一个图。一如既往,首先检查文件位置:

import pandas as pd
import scipy.stats as stats
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('C:\\...\\Data_Cortex_Nuclear.csv')
protein = df[['NR2A_N', 'class']].dropna()
sns.boxplot(x='class', y='NR2A_N', data = protein)
plt.show

在前面的代码中,我们确定了要比较的内容,在本例中,这些内容是蛋白质和类。然后我们将使用seaborn库创建箱线图,如下所示:

Figure 16.17 – Boxplot of the NR2A_N protein expression by class

图 16.17–NR2A_N 蛋白表达的箱线图(按类别)

从图中可以看出,我们的三体小鼠的分布因类别而异,没有刺激学习和注射生理盐水的小鼠的这种蛋白质表达范围更广。让我们试着将该蛋白质更改为数据集中的另一种蛋白质,即ITSN1\N蛋白质。以下屏幕截图显示了生成的箱线图:

Figure 16.18 – Boxplot of the ITSN1_N protein expression by class

图 16.18–ITSN1_N 蛋白表达的箱线图(按类别)

在这个特定的箱线图中,我们可以识别t-CS-mt-SC-m类中的异常值,即注射美金刚的两个小鼠类。这可能会告诉我们寻找更多关于美金刚注射和特定蛋白质之间关系的信息。*如果我们观察非三体小鼠,如果其他元素相同,这些数据(范围)的传播是否适用于该蛋白质?*在查看像这样的数据集时,我们会问自己一些问题。

如果你还记得,计算思维过程很少是一条直线。如果我们识别我们想在我们的算法中考虑的事情,我们不只是离开我们的算法,并决定它已经完成,所以我们不会改变它。我们回去再次确定我们需要什么,对我们的设计进行必要的修改,并再次创建我们的算法。这是我们在处理更大的数据集时发生的情况。我们看一些初始的可视化,可能创建一些不同类型的图,运行一些统计分析,然后决定下一步数据的去向。这只是对 Python 可能实现的功能的一瞥。

问题 7–使用 Python 分析股票

是时候玩弄一些股票了。您可以通过Quandl访问大量数据,这允许使用免费 API 进行教育用途。也有高级数据集可用。我们坚持教育目的,所以这应该足以满足我们的要求。

在这个问题中,我们将学习如何从 Quandl 中提取数据并查看 VZ 股票价格。VZVerizon股票价格的代码。我们将使用quandl来预测价格,这是 Python 的一个包,它是一个充满有用信息的网站。让我们来看看我们如何获取我们想要的信息。完整代码,减去 API 密钥,可以在我们的存储库中的ch16_stockAnalysis.py文件下找到:

  1. Let's take a look at how we can import the data. You'll need your own API for this. If you want to check another stock, say for AMZN, you'd substitute 'EOD/VZ' with 'WIKI/AMZ', for example. AMZN is the code for Amazon stock. But let's take a look at our VZ set:

    import quandl
    import numpy as np
    from sklearn.linear_model import LinearRegression
    from sklearn.svm import SVR
    from sklearn.model_selection import train_test_split
    #Get data from Quandl. Note that you'll need your own API to substitute in the api.key below.
    quandl.ApiConfig.api_key = '…'
    VZ = quandl.get('EOD/VZ')
    print(VZ.head())

    当我们运行前面的代码时,我们得到数据集中前五个值的表。以下屏幕截图显示了我们的值表:

    Figure 16.19 – EOD/VZ stock table

    图 16.19–EOD/VZ 库存表

  2. Now say we only wanted to focus on the adjusted close value in order to later make predictions. Then we can use the following code snippet to do so:

    #Grab the Adj_Close column
    VZ = VZ[['Adj_Close']]
    print(VZ.head())

    运行上述代码后,我们调整后的表如下所示:

Figure 16.20 – EOD/VZ adjusted close stock value table

图 16.20–EOD/VZ 调整后的收盘股票价值表

现在我们已经学会了提取当前数据,现在我们将使用一个数据集,我们已经将其放置在 GitHub 存储库中,这样我们就可以确保您能够复制结果。然后,您可以尝试使用 QuandlAPI 对当前数据执行此操作。

让我们来看一个数据文件名为 Ty0 T0 的数据集。其中包含 1983 年至 2020 年 4 月期间 VZ 的相同数据。*我们想从这个数据集中得到什么?*我们想做一些预测。因此,让我们建立这个模型。

请注意,代码相当大,因此包含您需要的所有内容的文件(减去您需要添加的第 15 行上的文件位置)位于ch16_predictionsModel.py中。但是让我们看看一些来自该文件的代码片段:

  1. The following code snippet will create a plot for our existing data in the dataset. It selects the Date column from the file and sets that as the index value. Then it creates a figure and adds the labels for the graph and axes:

    VZ["Date"]=pd.to_datetime(VZ.Date,format="%Y-%m-%d")
    VZ.index=VZ['Date']
    plt.figure(figsize=(16,8))
    plt.plot(VZ["Close"],label='Close price history')
    plt.title('Closing price over time', fontsize = 20)
    plt.xlabel('Time', fontsize = 15)
    plt.ylabel('Closing price', fontsize = 15)
    plt.show()

    我们还没有看到一个模型。我们还没有定义我们的训练数据。我们只是看看从19832020我们的股价发生了什么变化,如下所示。请注意,第一个记号标签上注明1984。可以看出,我们的数据是在1984之前开始的。自 1980 年以来,刻度线每 4 年一次,如下所示:

    Figure 16.21 – Closing price over time for VZ stock

    图 16.21–VZ 股票随时间变化的收盘价

    从前面的图表中可以看出,股票价格在任何方面都不是线性的。它们起起落落,又一次升起。一个预测模型需要大量的数据,以便我们准备尽可能好的预测。我们的数据集有 9166 行数据。很快就会派上用场的。

  2. Let's take a look at another snippet of code that we'll be using:

    VZ3=VZ2.values
    train_data=VZ3[0:750,:]
    valid_data=VZ3[750:,:]
    VZ2.index=VZ2.Date
    VZ2.drop("Date",axis=1,inplace=True)
    scaler=MinMaxScaler(feature_range=(0,1))
    scaled_data=scaler.fit_transform(VZ2)
    x_train_data,y_train_data=[],[]
    for i in range(60,len(train_data)):
        x_train_data.append(scaled_data[i-60:i,0])
        y_train_data.append(scaled_data[i,0])
    
    x_train_data,y_train_data=np.array(x_train_data),np.array(y_train_data)
    x_train_data=np.reshape(x_train_data,(x_train_data.shape[0],x_train_data.shape[1],1))

    注意代码的train_data=VZ3[0:750,:]行中的750值。这意味着我只使用 9166 行数据中的前 750 行来训练我的模型。这不太好。

    让我们看一下屏幕截图,它显示了运行这个预测模型时的结果。请注意,我们确实选择了将原始信息复制到我们的图形中。Python 将指出这是我们想要解决的一个可能的问题。这由你来决定。目前,将原始数据覆盖在我们的图表上,为我们提供了一个很好的视觉效果,以便对我们的模型进行比较:

    Figure 16.22 – Closing price predictions

    图 16.22–收盘价预测

    正如您在前面的图中看到的,这里用橙色显示,我们有原始的、复制的值。绿色显示了我们的模型所做的预测。他们并不可怕,但他们没有那么紧,因为他们可以。

  3. 让我们看看当我们使用 7500 行数据时会发生什么,这大约是可用数据的 82%。值得注意的是,GitHub 存储库中的文件使用的值为 7500,但是可以随意更改和调整这些值,以便测试模型的准确性。下图显示了我们的结果:

Figure 16.23 – Prediction model using 7,500 rows of data

图 16.23——使用 7500 行数据的预测模型

注意在这个模型中,实线和预测线是多么的接近。这是因为我们需要训练模型的数据越多,我们的预测就会越好。

在我们继续这个示例之前,请注意,这里没有涵盖整个代码文件。本书的其他部分已经讨论了一些代码,因此我们将重点放在算法的新部分,由于算法的复杂性,这些部分对算法解决方案至关重要。该代码文件的最后一部分确实使用了**长短时记忆(LSTM)**模型。LSTM 模型是一种人工递归神经网络。我们在机器学习中使用这个模型来创建深度学习模型。

*我们的模型会预测股票的价格吗?*没有。否则,我们在市场上都会过得更轻松。但是模型可以很好地预测价格,而不是价格,而是价格是否会上涨或下跌。

问题 8–使用 Python 创建卷积神经网络(CNN)

在本节中,我们将看一个使用人工智能AI的问题。更具体地说,我们将致力于创建一个卷积神经网络CNN。*那么什么是 CNN?*CNN 是一种深度学习算法。CNN 将图像作为输入。然后对图像进行处理并根据预先确定的条件给予重要性,这将有助于我们对图像进行区分和分类。

下图说明了卷积神经网络所涉及的过程:

Figure 16.24 – Convolutional neural network process

图 16.24–卷积神经网络过程

CNN 的创建是为了简化我们如何对图像进行分类,而不牺牲我们希望从图像分析中得到的预测的准确性。就好像我们用了一个过滤器。一旦我们应用了过滤器,我们就可以看到特性。上图显示了此过程的简化示意图。

我们将要研究的问题是手写训练和分析。考虑到计算思维过程,我们真正想做的是尽可能准确地分析笔迹。为此,我们分析成百上千的图像来创建和训练我们的模型。我们使用的图像越多,我们的模型就越精确。

对于我们的模型,我们将使用一个包含 70000 个图像的数据集。前 60000 张图像用于培训,而我们将使用其他 10000 张图像进行测试。完整代码可在ch16_CNN_mnist.py文件中找到。我们将查看该代码中的一些片段,并使用一些调整来显示其他组件。只要安装了所有必要的库和包,就可以在 GitHub 存储库中运行文件而无需进行更改。

让我们开始设计模型:

  1. Let's first take a look at a snippet of code that will upload the dataset, and then show the first item in the dataset:

    from keras.datasets import mnist
    #Grab the testing and training data from existing dataset
    (X_train, y_train), (X_test, y_test) = mnist.load_data()
    import matplotlib.pyplot as plt
    #Take a look at the first item in the dataset
    plt.imshow(X_train[0], cmap='Greys')

    我们使用训练集中的索引0来查看第一张图像。cmap属性将使颜色贴图变为灰色。你可以根据需要调整它。作为旁注,对于那些看不到颜色或有特殊颜色需求的人来说,更改颜色贴图可以显著改变图像的感知方式。让我们看看下面的截图中的第一张图片:

    Figure 16.25 – First image in the MNIST training set

    图 16.25–MNIST 培训集中的第一张图片

    从前面的屏幕截图中可以看到,这是一个手写样本,很可能是数字5中的一个。我们可以使用不同的索引再运行几次程序,以查看数据集中的其他样本。以下屏幕截图显示了其中一些示例及其相应的索引:

    Figure 16.26 – Sample images in the dataset by index

    图 16.26–数据集中按索引列出的示例图像

    我们使用的数据不是定量的,而是定性的。我们在看图像,所以我们需要一个能够分析这些图像的过程。为此,我们使用一个热编码,用新的二进制变量替换整数编码变量。

  2. Now that we've looked at what we're working with, let's reshape and encode our model using the following code snippet. As a reminder, the full code can be found in the repository, but some of the components will be slightly different (such as our file will not be testing the images in the dataset):

    #Reshape the model 
    X_train = X_train.reshape(60000,28,28,1)
    X_test = X_test.reshape(10000,28,28,1)
    from keras.utils import to_categorical
    #Use One-Hot encoding
    y_train = to_categorical(y_train)
    y_test = to_categorical(y_test)
    y_train[0]

    如您所见,我们正在将图像分为训练集和测试集。然后我们对它们进行编码。

  3. Once we have performed one-hot encoding, we can create our model:

    #Creating the model
    from keras.models import Sequential
    from keras.layers import Dense, Conv2D, Flatten
    model = Sequential()
    model.add(Conv2D(64, kernel_size=3, activation='relu', input_shape=(28,28,1)))
    model.add(Conv2D(32, kernel_size=3, activation='relu'))
    model.add(Flatten())
    model.add(Dense(10, activation='softmax'))
    #Compile the model
    model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

    在前面的代码片段中,我们使用了一个softmax函数。softmax函数有时被称为标准化指数函数。我们使用它来规范化输出。

  4. Now let's train the model. We're going to first fit the model and then validate the data. Take a look at this code snippet:

    #train the model
    model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=3)

    这是关于培训和测试的一件大事。也就是说,当我们理解和实践它们时,我们意识到只需要几行代码就可以完成一些非常惊人的事情。前面的两行代码(第三行是注释)将使一些伟大的事情发生,并允许我们的算法测试其他图像。

  5. Now we can predict the images in the dataset. We'll start with the last four, because everyone starts with the same four numbers, so I want to start backward this time. As a note, be patient. There are thousands of images to get through in this algorithm. While the epochs are running, you'll have a clock that will tell you how long until the information is processed. For this particular algorithm, it takes just a few minutes. Let's take a look at the snippet of code we'll need in order to run that prediction:

    #Predict last 4 images
    model.predict(X_test[9996:])

    当我们运行这段代码时,我们会得到一个非常密集的数字数组。请看下面的屏幕截图。我们强调了代码的一个关键部分以供讨论:

    Figure 16.27 – Model predictions for the CNN image

    图 16.27–CNN 图像的模型预测

    所以,我可以告诉你,预测的第一个数字是 3。*我们怎么知道数字代表 3?*因为每个列表代表数字 0 到 9。想象一下用[0,1,2,3,4,5,6,7,8,9]替换第一个列表。因此,如果我们将其视为索引,编号末尾带有01(在前面的屏幕截图中突出显示)的编号位于索引 3 中,即编号 3。所以我们的数字是 3,4,5 和 6。

  6. But do you trust the model? We can just go ahead and return to that snippet of code at the beginning of this discussion and print our results. Remember to change the code slightly to print your test images, and not the training images, as shown in the following code snippet:

    plt.imshow(X_test[9996], cmap='Greys')

    运行代码时,请记住,您需要为每个索引运行代码才能查看图像。以下屏幕截图显示了测试图像的每个相关索引的图像:

Figure 16.28 – Testing data verification images

图 16.28–测试数据验证图像

如您所见,我们的模型预测了这些索引中每个手写数字图像的正确值。

在我们结束本讨论之前,需要注意的是,这些模型目前在网站中被广泛使用,用于验证网站的访问者是人类还是机器人。一些网站会有验证码,有时会提供手写信件,用户必须识别才能继续。这些验证码也经常使用深度学习。CNN 和这类模型的应用是无穷无尽的。

总结

在本章中,我们能够探索计算思维的更多主题,特别是在使用 Python 编程语言处理数据和深入学习方面。我们学习了如何创建 pairplot 以确定数据集中变量之间的关系。我们还学习了如何生成各种类型的图来直观地表示我们的数据集。我们还学习了如何使用 Python 创建电场线。简言之,我们应用了我们在前几章学到的知识,并在处理应用问题时扩展了我们的知识。

这正是本书想要做的:展示各种各样的 Python 应用程序,同时在上下文中查看实际问题。*我们涵盖了 Python 所能做的一切了吗?*这是不可能的,因为 Python 的易用性、易学性和开放源代码特性使得它的功能不断增长。希望您能够使用一些新的脚本,了解一些您尚未探索的功能和功能,并喜欢探索这些场景。

*我们能说我们创造了完美的算法吗?*我们,这本书的作者,不这么认为。原因是我们一直在思考改进的方法。我们总是质疑其他应用程序。我们总是想让他们更有效率。而这正是计算思维帮助我们做到的。我们可以分析、设计、测试、返回,看看我们是否做了我们想要的,然后改进、重新设计、执行测试和重复。

希望在本章之后,您有机会练习并了解 Python 的更多功能。希望通过阅读本书,您有机会了解编程中计算思维的重要性。感谢您加入我们的旅程!