如何创建交互式 Dash Web 应用程序
使用 Dash、Heroku、XGBoost 和 Pickling 创建预测性 Web 应用程序
您已经完成了数据科学,现在您需要向全世界展示结果! Dash 是一个用于构建 web 应用的 python 框架。Dash 基于 Flask、Plotly.js 和 React.js 编写,非常适合快速构建定制的 web 应用程序。一旦构建完成,网络应用程序可以很容易地部署在云平台上,如 Heroku 。
先说最终产品。下面这个简单的 web 应用程序使用户能够确定一个面临竞价大战的房屋的预计价格。预测价格基于 2015 年至 2019 年在加利福尼亚州马林县出售的所有单户住宅的历史数据,收到两个或更多报价。用户可以选择面积,卧室数量,浴室数量,预期报价和上市价格的数量,应用程序将提供预测的销售价格。
要使用 web 应用程序,只需选择预测选项卡,选择标准,应用程序将返回预测的报价。有关目标、数据、评估协议和模型选择的说明,请使用解释选项卡。“评估”选项卡提供了用于评估预测相对于实际中标报价的准确性的指标。
如果您想了解如何开发自己的交互式 web 应用程序,请跟随我一步一步地指导您完成这个过程。
关于代码的一句话
该项目的所有代码、数据和相关文件都可以在 my GitHub 访问。安装 Dash 后,从代码所在的目录运行本地计算机上的代码,并从您的终端运行 python app.py 。这将在您的本地主机(127.0.0.1:8050)上运行应用程序。
数据科学
由于本文的重点是交互式 web 应用程序的创建,我将简要描述用于预测最佳投标价格的数据科学。详情请看 colab 笔记本这里。
原始数据是 2015 年至 2019 年在加利福尼亚州马林县出售的所有收到两个或更多报价的单户住宅的历史数据。导入原始数据并将区域映射到城市名称后,数据如下所示:
All Multiple Offer Sales in Marin County, CA 2015–2019
数据分为培训(2015 年至 2017 年)和验证(2018 年)以及测试(2019 年),培训和验证分别涉及 2,973 次销售和 991 次销售,测试涉及 776 次销售。该测试集包含 2019 年约 11 个月的数据。
# Split into train and test - 2015-2018 in train, 2019 in test
low_cutoff = 2015
high_cutoff = 2019
train = df[(df['Year'] >= low_cutoff) & (df['Year'] < high_cutoff)]
test = df[df['Year'] >= high_cutoff]# Split train into train and validation - 2015-2017 in train and 2018 in validation
cutoff = 2018
temp=train.copy()
train = temp[temp['Year'] < cutoff]
val = temp[temp['Year'] >= cutoff]
最初进行了简单的线性回归,结果非常好。然后运行一个 XGBoost 模型,它有稍微好一点的指标,因此被选为模型。
XGBoost Metrics
腌制
Pickling 用于序列化和反序列化 Python 对象(也称为编组或扁平化)。当您想要保存过程以便在以后进行预测而不必重新训练您的模型时,Pickling 在使用机器学习算法时非常有用。在我们的例子中,我们将清理管道,并在我们的 web 应用程序中使用它来进行预测。
首先,我们从 joblib 导入 dump:
from joblib import dump
接下来,我们运行 XGBoost 模型并转储管道。这实际上是将管道保存到本地磁盘上一个名为 pipeline.joblib 的文件中。然后,这个文件被加载到 GitHub 中,并在 web 应用程序的 predict.py 代码中使用。
# Encode and fit a XGBoost model
target = 'Selling Price'features = train.columns.drop(target)
X_train = train[features]
y_train = train[target]
X_val = val[features]
y_val = val[target]
X_test = test[features]
y_test = test[target]pipeline = make_pipeline(
ce.OneHotEncoder(use_cat_names=True),
XGBRegressor(n_estimators=200, n_jobs=-1)
)pipeline.fit(X_train, y_train)
dump(pipeline, 'pipeline.joblib')
y_pred = pipeline.predict(X_val)
Dash App
Dash 应用由定义应用外观的“布局”和创建交互性的“回调”组成。我们的基本 Dash 应用程序由 app.py 和 index.py 文件组成。如果你用过烧瓶,那么这段代码看起来会很熟悉!
app.py
import dashexternal_stylesheets = ['[https://codepen.io/chriddyp/pen/bWLwgP.css'](https://codepen.io/chriddyp/pen/bWLwgP.css')]app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config.suppress_callback_exceptions = True
server = app.server
app.py 文件只是初始化和实例化 Dash 应用程序。
index.py
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as htmlfrom app import app, server
from tabs import intro, predict, explain, evaluatestyle = {'maxWidth': '960px', 'margin': 'auto'}app.layout = html.Div([
dcc.Markdown('# Multiple Offer Calculator'),
dcc.Tabs(id='tabs', value='tab-intro', children=[
dcc.Tab(label='Intro', value='tab-intro'),
dcc.Tab(label='Predict', value='tab-predict'),
dcc.Tab(label='Explain', value='tab-explain'),
dcc.Tab(label='Evaluate', value='tab-evaluate'),
]),
html.Div(id='tabs-content'),
], style=style)[@app](http://twitter.com/app).callback(Output('tabs-content', 'children'),
[Input('tabs', 'value')])
def render_content(tab):
if tab == 'tab-intro': return intro.layout
elif tab == 'tab-predict': return predict.layout
elif tab == 'tab-explain': return explain.layout
elif tab == 'tab-evaluate': return evaluate.layoutif __name__ == '__main__':
app.run_server(debug=True)
index.py 文件是应用程序的主要可执行文件。它分为两个主要部分:布局和回调。我们先来看一下布局。
布局
Dash 提供了两套可视化组件: dash_html_components 和 dash_core_components 。dash_hml_components 库为每个 HTML 标签提供了一个组件。dash_core_components 库是更高级别的组件,如选项卡、下拉列表、降价模块、图表等。
对于我们的应用程序的布局,我们将使用 html 保持简单。dcc 部门。app.layout 定义了我们在 html 中的布局。Div(在 HTML 文档中定义一个部分)dcc。Markdown 使用 Markdown 和 dcc 创建标题。Tab 创建四个标签,标签在标签中可见,一个值用于编码。就这样——我们基本上已经创建了主页!
回调
Dash 使用 @app.callback decorator 告诉应用程序如何处理输入和输出。在我们的应用程序中,输入是布局 dcc 中定义的 id='tabs 。有四个子项的选项卡—介绍、预测、解释和评估。输出是在 html.Div 中定义的 id='tabs-content '。当用户单击一个选项卡时,输入识别该选项卡,调用 render_content(tab) 构造函数(函数)将选项卡更改为被单击的选项卡,然后结果输出到 html.Div。就这样——一个非常简单的回调!
预测选项卡
了解了基础知识之后,让我们用预测选项卡来看看一个更复杂的例子。在 predict.py 代码中,我们将使用一个下拉菜单和四个滑动标签来获取我们的预测输入。然后,输入将用于运行我们的 pickled 预测并输出结果。
style = {'padding': '1.5em'}layout = html.Div([
dcc.Markdown("""
### Predict
Use the controls below to update your predicted offer, based on city,
beds, baths, number of offers, and list price.
"""),html.Div(id='prediction-content', style={'fontWeight': 'bold'}),html.Div([
dcc.Markdown('###### Area'),
dcc.Dropdown(
id='area',
options=[{'label': city, 'value': city} for city in cities],
value=cities[10]
),
], style=style),html.Div([
dcc.Markdown('###### Bedrooms'),
dcc.Slider(
id='bedrooms',
min=1,
max=7,
step=1,
value=3,
marks={n: str(n) for n in range(1, 7, 1)}
),
], style=style),html.Div([
dcc.Markdown('###### Baths'),
dcc.Slider(
id='baths',
min=1,
max=9,
step=1,
value=2,
marks={n: str(n) for n in range(1, 9, 1)}
),
], style=style),html.Div([
dcc.Markdown('###### Number of Offers'),
dcc.Slider(
id='offers',
min=2,
max=15,
step=1,
value=3,
marks={n: str(n) for n in range(2, 15, 1)}
),
], style=style),html.Div([
dcc.Markdown('###### Listing Price'),
dcc.Slider(
id='list_price',
min=1000000,
max=3000000,
step=100000,
value=1500000,
marks={n: f'{n/1000:.0f}k' for n in range(1000000, 3000000, 100000)}
),
], style=style),])[@app](http://twitter.com/app).callback(
Output('prediction-content', 'children'),
[Input('area', 'value'),
Input('bedrooms', 'value'),
Input('baths', 'value'),
Input('offers', 'value'),
Input('list_price', 'value')])
def predict(area, bedrooms, baths, offers, list_price):year = 2019
df = pd.DataFrame(
columns=['Year', 'Area', 'Total Bathrooms', 'Bedrooms', 'Curr List Price', 'Number of Offers'],
data=[[year, area, baths, bedrooms, list_price, offers]]
)pipeline = load('model/pipeline.joblib')
y_pred_log = pipeline.predict(df)
y_pred = y_pred_log[0]
percent_over = ((y_pred - list_price) / list_price) * 100
per_offer = percent_over / offers
results = f'The predicted winning bid is ${y_pred:,.0f} which is {percent_over:.2f}% over the asking price or \
{per_offer:.2f}% per offer.'return results
虽然这看起来可能有很多代码,但实际上非常简单。该布局仅由四个组件组成——html。dcc 部门。降价,dcc。我们的布局由六个 html 组成。Div (sections ),预测在第一节,组件在接下来的五节。五个组件提供输入。
每当任何单个输入发生变化时,都会调用回调函数,调用预测函数并将结果输出到第一部分。
注意在预测函数中:
pipeline = load(’ model/pipeline . joblib ')
这将加载转储的管道,允许使用很少的代码非常快速地进行预测。
这是对 Dash 的一个非常简单的介绍。如需了解更多详情,请查看 Dash 文档此处。
Heroku 部署
一旦你让交互式网络应用在本地运行,你就可以让其他人通过使用公共托管服务(比如 Heroku)来访问它。Heroku 将托管该应用程序,允许您链接到它或使用 iframe。
在 Heroku 上托管的基本步骤是:
1.创建一个 Procfile 和 requirements.txt 文件。在我的[GitHub][4]里看到我的。
2.创建一个 Heroku 应用程序并连接到您的 GitHub 存储库。
3.运行应用程序!
我欢迎建设性的批评和反馈,请随时给我发私信。
有关 web 应用程序的更多背景信息,请参见配套文章“如何赢得房地产投标战”。
这篇文章最初出现在我的 GitHub Pages 网站上。
在推特上关注我
马林房地产数据来源:马林 MLS (BAREIS),2015–2019 数据
如何使用 Python 和 Bokeh 创建交互式地理地图
使用 Choropleth 地图进行交互式数据可视化
如果你正在寻找一种强大的方法来可视化地理数据,那么你应该学会使用交互式 Choropleth 地图。Choropleth 地图通过预定地理区域(例如国家、州或县)上的各种阴影图案或符号来表示统计数据。静态 Choropleth 图对于显示数据的一个视图很有用,但是交互式 Choropleth 图更强大,并且允许用户选择他们更喜欢查看的数据。
下面的互动图表提供了旧金山独栋房屋销售的细节。该图表按中位数销售价格、最低收入要求、平均销售价格、每平方英尺平均销售价格、平均平方英尺和销售数量(10 年的数据)对单户家庭房屋销售进行了细分。
如果您想了解如何开发自己的交互式地图,请跟随我一步一步地指导您完成这个过程。
关于代码的一句话
该项目的所有代码、数据和相关文件都可以在 my GitHub 访问。在 Bokeh 服务器上运行的最终 Colab 代码可以在这里找到。跳过数据清理和争论步骤的 Colab 代码的测试版本可以在这里找到。
使用 Python 和散景
在探索了几种不同的方法之后,我发现 Python 和 Bokeh 的结合是创建交互式地图的最直接、最有据可查的方法。
让我们从图表所需的安装和导入开始。Pandas、numpy 和 math 是用于清理和争论数据的标准 Python 库。geopandas、json 和 bokeh 导入是映射所需的库。
我在 Colab 工作,需要安装 fiona 和 geopandas。
!pip install fiona
!pip install geopandas
进口
*# Import libraries*
**import** **pandas** **as** **pd**
**import** **numpy** **as** **np**
**import** **math**
**import** **geopandas**
**import** **json**
**from** **bokeh.io** **import** output_notebook, show, output_file
**from** **bokeh.plotting** **import** figure
**from** **bokeh.models** **import** GeoJSONDataSource, LinearColorMapper, ColorBar, NumeralTickFormatter
**from** **bokeh.palettes** **import** brewer
**from** **bokeh.io.doc** **import** curdoc
**from** **bokeh.models** **import** Slider, HoverTool, Select
**from** **bokeh.layouts** **import** widgetbox, row, column
数据加载、清理和争论
因为本文的重点是交互式地图的创建,所以我将简要描述用于加载、清理和争论数据的步骤。有兴趣可以在这里查看完整的清洗和角力。
由于我有房地产许可证,我可以访问旧金山 MLS,我过去常常将 10 年(2009 年至 2018 年)的单户住宅销售数据下载到 sf_data 数据框架中。
一个重要的数据,房屋面积,大约 16%的数据为零。填充数据的一个合理方法是使用旧金山所有单户家庭卧室的平均房屋面积。例如,所有价值为零的一居室房屋都用旧金山所有一居室房屋销售的平均平方英尺来填充。
数据的关键列是邻居代码,它需要匹配邻居的映射代码。这将允许我们将数据与地图合并。字典用于更改数据中的邻域代码以匹配地图中的邻域代码。
最后,将年份和每平方英尺价格列添加到 sf_data 中,并使用 groupby 和聚合函数对 sf_data 进行汇总,以创建最终的 neighborhood_data 数据帧,其中所有数值字段都转换为整数值,以便于显示数据:
neighborhood_data DataFrame
neighborhood_data 数据框显示了按街区汇总的单户住宅销售情况。现在我们需要将这些数据映射到旧金山的社区地图上。
以下是已清理数据的快捷方式:
neighborhood_data = pd.read_csv('https://raw.githubusercontent.com/JimKing100/SF_Real_Estate_Live/master/data/neighborhood_data.csv')
准备测绘数据和地理数据框架
Bokeh 提供了几种处理地理数据的方法,包括切片提供商地图、Google 地图和 GeoJSON 数据。我们将使用 GeoJSON,这是一个流行的开放标准,用于用 JSON 表示地理特征。JSON (JavaScript Object Notation)是一种最小的、可读的数据结构化格式。散景使用 JSON 在散景服务器和 web 应用程序之间传输数据。
在典型的散景交互式图形中,数据源需要是 ColumnDataSource。这是散景中的一个关键概念。但是,在使用地图时,您可以使用 GeoJSONDataSource。
为了使我们在 Python 中处理地理空间数据更容易,我们使用了 GeoPandas。它结合了 pandas 和 shapely 的功能,在 pandas 中提供地理空间操作,并为 shapely 提供多种几何图形的高级接口。我们将使用 GeoPandas 创建地理数据框架,这是创建 GeoJSONDataSource 的前奏。
最后,我们需要一张 geojson 格式的地图。旧金山,通过他们的 DataSF 网站,有一个 geojson 格式的可导出的邻居地图。
让我们通过以下代码展示如何创建地理数据框架。
*# Read the geojson map file for Realtor Neighborhoods into a GeoDataframe object*
sf = geopandas.read_file('https://raw.githubusercontent.com/JimKing100/SF_Real_Estate_Live/master/data/Realtor%20Neighborhoods.geojson')
*# Set the Coordinate Referance System (crs) for projections*
*# ESPG code 4326 is also referred to as WGS84 lat-long projection*
sf.crs = {'init': 'epsg:4326'}
*# Rename columns in geojson map file*
sf = sf.rename(columns={'geometry': 'geometry','nbrhood':'neighborhood_name', 'nid': 'subdist_no'}).set_geometry('geometry')
*# Change neighborhood id (subdist_no) for correct code for Mount Davidson Manor and for parks*
sf.loc[sf['neighborhood_name'] == 'Mount Davidson Manor', 'subdist_no'] = '4n'
sf.loc[sf['neighborhood_name'] == 'Golden Gate Park', 'subdist_no'] = '12a'
sf.loc[sf['neighborhood_name'] == 'Presidio', 'subdist_no'] = '12b'
sf.loc[sf['neighborhood_name'] == 'Lincoln Park', 'subdist_no'] = '12c'
sf.sort_values(by=['subdist_no'])
我们使用 geopandas 将 geojson 地图读入地理数据框架 sf 。然后,我们将坐标参考系统设置为经纬度投影。接下来,我们重命名几个列,并使用 set_geometry 将地理数据框设置为包含活动几何(要绘制的形状的描述)的“几何”列。最后,我们清理一些邻居 id 来匹配邻居数据。
sf GeoDataFrame
我们现在在 neighborhood_data 中有我们的邻居数据,在 sf 中有我们的映射数据。请注意,它们都有共同的列 subdist_no(邻域标识符)。
为 GeoJSONDataSource 创建 JSON 数据
我们现在需要创建一个函数,将我们的邻居数据与我们的地图数据合并,并将其转换为 Bokeh 服务器的 JSON 格式。
*# Create a function the returns json_data for the year selected by the user*
**def** json_data(selectedYear):
yr = selectedYear
*# Pull selected year from neighborhood summary data*
df_yr = neighborhood_data[neighborhood_data['year'] == yr]
*# Merge the GeoDataframe object (sf) with the neighborhood summary data (neighborhood)*
merged = pd.merge(sf, df_yr, on='subdist_no', how='left')
*# Fill the null values*
values = {'year': yr, 'sale_price_count': 0, 'sale_price_mean': 0, 'sale_price_median': 0,
'sf_mean': 0, 'price_sf_mean': 0, 'min_income': 0}
merged = merged.fillna(value=values)
*# Bokeh uses geojson formatting, representing geographical features, with json*
*# Convert to json*
merged_json = json.loads(merged.to_json())
*# Convert to json preferred string-like object*
json_data = json.dumps(merged_json)
**return** json_data
我们向 json_data 函数传递我们希望加载的数据年份(例如 2018 年)。然后,我们从 neighborhood_data 中提取所选年份的数据,并将其与 sf 中的映射数据合并。在用零填充空值(没有销售的街区,比如金门公园)之后,我们使用 json.loads 和 json.dumps 将合并的文件转换成 json 格式,在 json_data 中返回 JSON 格式的数据。
互动地图主要代码
我们仍然需要几段代码来制作交互式地图,包括彩条、散景小部件和工具、绘图功能和更新功能,但在我们详细讨论这些部分之前,让我们先看看主要代码。
*# Input geojson source that contains features for plotting for:*
*# initial year 2018 and initial criteria sale_price_median*
geosource = GeoJSONDataSource(geojson = json_data(2018))
input_field = 'sale_price_median'
*# Define a sequential multi-hue color palette.*
palette = brewer['Blues'][8]
*# Reverse color order so that dark blue is highest obesity.*
palette = palette[::-1]
*# Add hover tool*
hover = HoverTool(tooltips = [ ('Neighborhood','@neighborhood_name'),
('# Sales', '@sale_price_count'),
('Average Price', '$@sale_price_mean{,}'),
('Median Price', '$@sale_price_median{,}'),
('Average SF', '@sf_mean{,}'),
('Price/SF ', '$@price_sf_mean{,}'),
('Income Needed', '$@min_income{,}')])
*# Call the plotting function*
p = make_plot(input_field)
*# Make a slider object: slider*
slider = Slider(title = 'Year',start = 2009, end = 2018, step = 1, value = 2018)
slider.on_change('value', update_plot)
*# Make a selection object: select*
select = Select(title='Select Criteria:', value='Median Sales Price', options=['Median Sales Price', 'Minimum Income Required',
'Average Sales Price', 'Average Price Per Square Foot',
'Average Square Footage', 'Number of Sales'])
select.on_change('value', update_plot)
*# Make a column layout of widgetbox(slider) and plot, and add it to the current document*
*# Display the current document*
layout = column(p, widgetbox(select), widgetbox(slider))
curdoc().add_root(layout)
让我们来分解代码:
- 用我们 2018 年的初始数据创建我们的 GeoJSONDataSource 对象。
- 定义用于颜色条和邻域映射值的调色板。
- 添加一个 Bokeh HoverTool,当鼠标悬停在某个邻域上时显示数据。
- 调用绘图函数,使用 sale_price_median 作为 initial_data(中间销售价格)来创建地图绘图。
- 添加一个 Bokeh Slider 小部件,使用户能够根据年份更改数据。
- 添加一个 Bokeh Select 小部件,使用户能够根据标准(例如,中等销售价格或最低收入要求)选择数据。
- 在列中布局地图地块和微件,并将结果输出到由散景服务器显示的文档中。
彩条
彩条比我想象的要更有挑战性。原来,彩条是“附加”在绘图上的,当要求更改标准时,整个绘图都需要刷新。每个标准都有自己独特的最小和最大范围、显示格式和描述。例如,“销售额”的范围为 0-100,格式为整数,名称“销售额”需要在图的标题中更改。所以我创建了一个 format_df ,它详细描述了颜色栏和标题中需要的数据。
# This dictionary contains the formatting for the data in the plots
format_data = [('sale_price_count', 0, 100,'0,0', 'Number of Sales'),
('sale_price_mean', 500000, 4000000,'$0,0', 'Average Sales Price'),
('sale_price_median', 500000, 4000000, '$0,0', 'Median Sales Price'),
('sf_mean', 500, 5000,'0,0', 'Average Square Footage'),
('price_sf_mean', 0, 2000,'$0,0', 'Average Price Per Square Foot'),
('min_income', 50000, 600000,'$0,0', 'Minimum Income Required')
]
#Create a DataFrame object from the dictionary
format_df = pd.DataFrame(format_data, columns = ['field' , 'min_range', 'max_range' , 'format', 'verbage'])
format_df DataFrame
悬浮工具
HoverTool 是一个相当简单的散景工具,允许用户将鼠标悬停在某个项目上并显示值。在主代码中,我们插入 HoverTool 代码,告诉它使用基于 neighborhood_name 的数据,并显示六个标准,使用“@”来表示列值。
*# Add hover tool*
hover = HoverTool(tooltips = [ ('Neighborhood','@neighborhood_name'),
('# Sales', '@sale_price_count'),
('Average Price', '$@sale_price_mean{,}'),
('Median Price', '$@sale_price_median{,}'),
('Average SF', '@sf_mean{,}'),
('Price/SF ', '$@price_sf_mean{,}'),
('Income Needed', '$@min_income{,}')])
Widgets 和回调函数
我们使用两个散景部件,滑块对象和选择对象。在我们的示例中,Slider 对象允许用户选择要显示的年份(或行), select 对象允许用户选择标准(或列)。
这两个小部件的工作原理相同——回调。在下面的代码中,小部件传递一个“值”并调用一个名为 update_plot 的函数。调用 on_change 方法(当使用小部件(事件处理程序)进行更改时)。
*# Make a slider object: slider*
slider = Slider(title = 'Year',start = 2009, end = 2018, step = 1, value = 2018)
slider.on_change('value', update_plot)
*# Make a selection object: select*
select = Select(title='Select Criteria:', value='Median Sales Price', options=['Median Sales Price', 'Minimum Income Required',
'Average Sales Price', 'Average Price Per Square Foot',
'Average Square Footage', 'Number of Sales'])
select.on_change('value', update_plot)
回调函数 update_plot 有三个参数。attr 参数只是您传递的“值”(例如 slider.value 或 select.value),新旧参数是散景使用的内部参数,您不需要处理它们。
根据所使用的小部件,我们或者基于年份(yr)选择 new_data (Slider ),或者基于条件(cr)重新设置 input_field (Select)。然后,我们根据当前的 input_field 重新设置绘图。
最后,我们布局图和小部件,清除旧文档并输出包含新数据的新文档。
*# Define the callback function: update_plot*
**def** update_plot(attr, old, new):
*# The input yr is the year selected from the slider*
yr = slider.value
new_data = json_data(yr)
*# The input cr is the criteria selected from the select box*
cr = select.value
input_field = format_df.loc[format_df['verbage'] == cr, 'field'].iloc[0]
*# Update the plot based on the changed inputs*
p = make_plot(input_field)
*# Update the layout, clear the old document and display the new document*
layout = column(p, widgetbox(select), widgetbox(slider))
curdoc().clear()
curdoc().add_root(layout)
*# Update the data*
geosource.geojson = new_data
创建绘图功能
地图的最后一部分是 make_plot,绘图函数。让我们来分解一下:
- 我们将 field_name 传递给它,以指示我们要绘制哪一列数据(例如,销售价格中值)。
- 使用 format_df,我们为颜色条提取最小范围、最大范围和格式。
- 我们调用 Bokeh 的 LinearColorMapper 来设置调色板和颜色条的范围。
- 我们使用 Bokeh 的 NumeralTickFormatter 和 ColorBar 创建了 ColorBar。
- 我们创建具有适当标题的绘图图形。
- 我们使用 Bokeh 的 p.patches 字形和 geosource 中的数据创建“面片”,在我们的例子中是邻域多边形。
- 我们将 colorbar 和 HoverTool 添加到绘图中,并返回绘图 p。
*# Create a plotting function*
**def** make_plot(field_name):
*# Set the format of the colorbar*
min_range = format_df.loc[format_df['field'] == field_name, 'min_range'].iloc[0]
max_range = format_df.loc[format_df['field'] == field_name, 'max_range'].iloc[0]
field_format = format_df.loc[format_df['field'] == field_name, 'format'].iloc[0]
*# Instantiate LinearColorMapper that linearly maps numbers in a range, into a sequence of colors.*
color_mapper = LinearColorMapper(palette = palette, low = min_range, high = max_range)
*# Create color bar.*
format_tick = NumeralTickFormatter(format=field_format)
color_bar = ColorBar(color_mapper=color_mapper, label_standoff=18, formatter=format_tick,
border_line_color=**None**, location = (0, 0))
*# Create figure object.*
verbage = format_df.loc[format_df['field'] == field_name, 'verbage'].iloc[0]
p = figure(title = verbage + ' by Neighborhood for Single Family Homes in SF by Year - 2009 to 2018',
plot_height = 650, plot_width = 850,
toolbar_location = **None**)
p.xgrid.grid_line_color = **None**
p.ygrid.grid_line_color = **None**
p.axis.visible = **False**
*# Add patch renderer to figure.*
p.patches('xs','ys', source = geosource, fill_color = {'field' : field_name, 'transform' : color_mapper},
line_color = 'black', line_width = 0.25, fill_alpha = 1)
*# Specify color bar layout.*
p.add_layout(color_bar, 'right')
*# Add the hover tool to the graph*
p.add_tools(hover)
**return** p
将所有这些放在一起
测试代码将所有这些放在一起,用 Colab 笔记本中的 ColorBar 和 HoverTool 打印出一个静态地图。为了使用滑块和选择来查看交互式组件,您需要在接下来的步骤中使用散景服务器。(您将需要 fiona 和 geopandas 导入来运行下面的代码)
带彩条和悬浮工具的静态地图
散景服务器
我使用 2018 年的数据和 Colab 中的中值销售价格开发了静态地图,以便在添加互动部分之前让大部分代码工作。为了测试和查看散景的交互式组件,您需要遵循以下步骤。
- 在电脑上安装散景服务器。
- 下载。ipynb 文件复制到计算机上的本地目录中。
- 从终端将目录更改为带有。ipynb 文件。
- 从终端运行以下命令:bokeh serve(两个破折号)show filename.ipynb
- 这将在您的浏览器上打开一个本地主机,并输出您的交互式图形。如果有错误,应该可以在终端中看到。
公众通过 Heroku 进入互动图表
一旦你让交互式图形在本地工作,你就可以让其他人通过使用一个公共的散景托管服务(比如 Heroku)来访问它。Heroku 将托管交互式图形,允许您链接到它(如本文中所示)或使用 iframe,如在我的 GitHub Pages 站点上。
在 Heroku 上托管的基本步骤是:
- 更改 Colab 笔记本,注释掉 fiona 和 geopandas 的安装。Heroku 拥有这些项目,如果它们出现在代码中,构建将会失败。
- 更改 Colab 笔记本,注释掉最后两行(output_notebook()和 show§)。
- 将 Colab 笔记本下载为. py 文件,并上传到 GitHub 存储库。
- 创建一个 Heroku 应用程序并连接到包含您的。py 文件。
- 创建一个 Procfile 和 requirements.txt 文件。在我的 GitHub 里看到我的。
- 运行应用程序!
我欢迎建设性的批评和反馈,请随时给我发私信。
在推特上关注我
这篇文章最初出现在我的 GitHub Pages 网站上,交互图也可以在走向数据科学文章旧金山理工就业?先查房价!
如何创建获奖的数据可视化
如何创建出色的数据可视化的分步指南。让您的数据脱颖而出的技巧和想法!
Chart from award-winning kernel from Kaggle competition. Let’s learn how to create it from scratch!
本周早些时候,我带着我的笔记本在 Kaggle 的机器学习和数据科学调查竞赛中获得了三等奖(6000 美元)【外面有工作吗?Kaggle vs 玻璃门。
虽然竞赛评估了我作品的几个方面,但我认为我展示信息的方式是获奖的关键。在这里,我想分享一点构建数据可视化背后的思考过程,一步一步地说明。
要绘制的数据
我的想法是衡量不同国家有多少人在不同的岗位(职称)上工作。
Data that I want to plot!
第一个情节
我选择使用 Plotly 主要是因为我已经习惯了它,也因为我喜欢它提供的开箱即用的交互性。然而,我所应用的概念,以及我将要演示的概念,可以用于任何其他图形库或软件,与语言无关。
First attempt to plot data
First attempt to plot data by country
选择更好的绘图类型
我对这个可视化的条形图不满意。我想显示相同的信息,但允许比较不同的国家。为各个国家添加多个条形图看起来一点也不好。然后我试了一个折线图,因为添加多条线比多列效果更好。
Choosing a Line Plot
好多了…现在让我们尝试添加国家,而不是所有国家的总和。
Trying a line plot per country.
比栅栏看起来好多了。但还是不对。我的下一个想法是把 x 轴转换成径向。
Radial plot by country
这看起来很有趣!我想我可以继续使用这种图表类型。
将要绘制的数据从绝对数据更改为相对数据
一些国家比其他国家有更多的绝对行。这在图表中造成了失真,因此我将改变指标,绘制每个国家每个职位的相对百分比。它应该允许我们比较它们!
Plotting relative values (percentages)
确实!现在所有国家的规模都一样。按比例比较比绝对值比较好得多。
关闭线路
这有点棘手。要在 Plotly 上“关闭”雷达图,您需要将第一个数据点再次添加到末尾。
Radar chart, with all lines closed
在轴标题中创建层次结构
如果你看看轴,他们目前没有一个层次或任何特定的顺序。我想通过从最不专业到最专业的相似的职位名称来创建一个。对我来说,按照以下顺序组织是有意义的:
商业分析师< Data Analyst < Data Scientist < Data Engineer/DBA < Software Engineer < Statistician/Research Scientist
Adding a hierarchy to the axis
Decluttering
This is the most important part of any good data visualization. Remove any noise that is not directly contributing to how people are reading and interpreting data.
Turning background to white
Now that the background is white, we also need to change some other elements, such as grids, ticks and lines. Here my choices were:
- Turn all text and chart elements to a light grey
- Hide any chart grid and axis lines that are not essential. I only kept radial axis grid (the circles), because they are important for readers to understand the magnitude of the values displayed.
Declutter background
It looks much better now, doesn’t it?
Smoothing all lines, and making them grey and thinner
Now we will transform all lines to grey, reduce their width and also make them less sharp by applying some smoothing.
Bringing lines to background
This is 好多了!因为现在我们实际上可以“看到”每一行了!但正如他们所说,细节决定成败。让我们继续改进它吧!
删除图例,调整网格和范围
- 现在,我认为有太多的网格线(0,10,20,…,50)塞满了图表。我不喜欢它,相反,我将只创建三行(25%和 50%)。
- 我也不喜欢为一个传奇人物设定那么多的值,它们除了让我们的形象变得更糟之外,没有任何帮助。让我们把它藏起来!
- 有一行几乎超过了数据科学家轴标题,我将稍微增加一点范围以避免这种情况。
Hiding legends and adjusting grid
调整悬停信息
Hover does not look good
当我们将鼠标悬停在数据点上时,我们会看到 r 和θ值。这对于查看图表的任何人来说都没有信息。让我们在那里调整一些事情。
- 添加国家名称(这样无需多种颜色或图例,就可以轻松将该系列与国家联系起来)
- 添加数据点(这样很容易将每个数据点的值与每一行相关联)
- 将数据点格式化为不带小数点的百分比(不需要任何小数点,因为分析更加定性)
After adjusting hover information
讲故事
现在,我们将重点介绍一些我们想讲述的特定国家。在这张图表中,我选择美国对中国。我们将做什么:
- 为突出显示的国家/地区线条增添色彩
- 从国旗颜色中选择颜色(红色代表中国,蓝色代表美国)
- 增加突出显示的国家线的宽度
- 增加突出显示的国家线的不透明度
- 仅对突出显示的国家显示图例
Highlighting data to tell a story
现在我们用这些数据来讲述一些故事!我们能够看到中国和美国之间的差异!从这张图表中我们可以很容易地得出一些结论!
添加有意义的标题
现在,我们将向图表添加一个有意义的标题和数据源。
- 标题字体更大
- 源的较小字体
- 两者都是灰色的,不会引起太多注意
Adding title and source
将所有要素更紧密地联系在一起
使用 Plotly 的标准自动调整大小会导致所有元素彼此之间的间隔过大,让我们通过定义图表的高度和宽度大小来拉近它们。
另外对图例也做了一些小的调整:
- 将颜色更改为灰色
- 单击并双击时更改行为
Legend is now grey, all elements are more close together
为什么它是好的?
这个图表很容易让我们比较两个不同的国家。同时,它还保留了未被纳入相关报道的所有其他国家的数据,从而为报道提供了更多的背景信息。
读者的注意力会被吸引到数据本身,而不是其他图表元素。故事/比较突出显示且清晰,标题与故事相关。这个图表只讲述了一个故事。
颜色是明智的选择,也有意义(国旗颜色)。所有其他不属于故事的元素都以灰色背景。
这个消息来源被清楚地引用,并没有引起太多的关注。
关于如何进行出色的数据讲述的更多提示
保持所有图表相似
显示多个图表时,请坚持使用几种不同的图表类型。这样做的目的是让读者的生活更轻松,因为他们不需要学习如何阅读每一个新图表——在学习如何解释一个图表之后,阅读所有其他图表将是自动的。
在每个图表中坚持使用几种颜色
如果你突出显示的数据颜色没有任何意义(不像这个例子,他们对国旗的颜色进行编码),那么你就不应该使用很多不同的颜色。尽量减少。
每个图表只讲一个故事
在一张图表中突出多种事物可能很有诱惑力。相反,创建各种图表来突出不同的东西,每个图表一个独特的故事。
请参阅构建这些图表的完整代码
如何使用 R 和 dygraph 创建更好的交互式预测图
如果你对 R 和时间序列感兴趣,你一定会偶然发现罗伯·海曼的伟大的预测包。除了用于分析时间序列的各种工具和方法之外,它还扩展了 ggplot 以使用 autoplot 可视化预测对象。虽然这几乎不用代码就能产生很好的结果,但它不提供交互功能。在本文中,您将了解到…
- 如何使用交互式功能(如缩放、平移和鼠标悬停信息)绘制预测
- 如何在绘图中包含 80%和 95%的区间预测
- 如何编写 JavaScript 格式化程序来调整图例
这是结果的样子…
对预测对象使用自动批次
让我们先看看预测对象的基本自动绘图功能的结果。在经典的航空公司数据集上创建一个 3 年预测,并绘制出结果,只需要三行代码。
code that forecasts and plots the air passenger time series
autoplot of a forecast object
你可以看到黑色的实际时间序列和蓝色的预测。预测区间(80%和 95%)也显示为蓝色区域。虽然这对于三行代码来说无疑是一个好结果,但是可以通过交互特性来改善这个结果。
将 dygraph 用于预测对象
JavaScript 库 dygraph 可以创建交互式绘图,R 的这个库的接口也可以通过dy graph 包获得。
将上面的例子转换成使用 dygraph 只是增加了一行来绑定来自 forecast 对象的时间序列。
simple dygraph for a forecast object
basic dygraph showing actuals and point forecast
现在,虽然我们获得了 dygraph 的交互特性,但突然之间预测区间丢失了。在 dygraph 中,可以用所谓的误差线来绘制时间序列,以解决这个问题。由于 dygraph 只支持每个时间序列一个误差线,我们只是简单地为每个时间间隔添加一个时间序列。
adding error bars for the interval forecasts
dygraph showing actuals, point and interval forecasts
那看起来相当好,但是有一点东西不见了。如果将鼠标悬停在图表上,您将只能看到图例中的点预测值(上图中的 569.93),而看不到相应的区间。
为预测间隔编写自定义格式化程序
使用dyAxis
函数的valueFormatter
参数,自定义 JavaScript 函数可以覆盖 dygraph 图例中值的格式。对于每个时间序列,将在鼠标悬停时调用 JavaScript 函数,该函数将接受六个参数:
num
:当前时间序列鼠标悬停位置的值opts
:当前动态图的选项值seriesName
:当前时间序列的名称g
:实际的 dygraph 对象row
:鼠标当前所在位置的原始数据的行索引col
:当前时间序列的原始数据列索引
将传递给函数的值num
不包括间隔值。但是,给定行和列索引的值可以从 dygraph 对象(函数getValue
)中获得,并且将包含这个预测间隔。然后,我们可以根据自己的喜好对其进行格式化。重用内置的Dygraph.numberValueFormatter
函数来格式化和传递选项值将保持对选项的支持,例如控制要显示的位数(参见dyOptions
中的选项digitsAfterDecimal
)。
请注意,dygraph 返回的值将是一个长度为 3 的向量,即使对于像实际时间序列这样只有一个值的时间序列也是如此。因此,在格式化为一个区间之前,我添加了检查上限值和下限值是否实际不同。
custom JavaScript for formatting values in the legend
此外,我对图表进行了一些额外的调整:
- 点预测的专用时间序列,用于将间隔预测与图例中的点预测分开
- 使用
dyLegend
函数中的选项labelsSeparateLines
将每个标签放在一个单独的行上,这使得结果更具可读性 dyRangeSelector
函数在图的底部放置了一个漂亮的选择器- 使用选项
digitsAfterDecimal
将位数减少到一位 - 一个小的 CSS 保持图例半透明,以避免覆盖图形
final code using dygraph for plotting forecast objects plot
dygraph showing actuals, point and interval forecasts and custom legend
感谢您的阅读!
如何使用 jupyter 笔记本、reveal.js、github 上的主机创建数据驱动的演示文稿,并向世界展示:第一部分—制作基本的幻灯片
…其中我讨论了一个工作流程,您可以开始在 jupyter 笔记本上写内容,创建 reveal.js 幻灯片,并将其放在 github 上进行演示。这是一个非常简单的演示,你可以完全控制自己
A first simple slide deck
第一部分:基本幻灯片组
第二部分:使用备注的基本幻灯片组
第三部分:高级技术
逐步地
建立 github repo 并添加子模块
第一步 。首先创建一个 github 存储库来存放您的幻灯片。要做到这一点,请访问https://www.github.com并启动一个存储库,您还需要安装 git。我在 Vultr 上使用了一个托管实例,它附带了一个预装的 git。如果您使用 Windows、Mac 或 Linux,您可能希望安装 git,或者在您的终端中检查您已经安装了 git,方法是发出如下命令:
git --version
Click on the + sign to add a repository
第二步 。添加存储库。例如,我创建了一个名为 *myJupyterSlides 的存储库,*请看下面的截图:
Created an empty repository to host jupyter notebook based slides
第三步 。(仍然使用 web 界面)最好在主分支中创建一个 index.md 文件,并说明您将在此存储库中保存您的幻灯片。为此,您也可以使用“README.md”。现在让我们创建一个文件。下面您可以看到文件是这样创建的:
In step 3 create a new file labelled as index.md
第四步 。(仍然使用 web 界面),使用 web 界面,创建一个名为 gh-pages 的新“分支”(参见下面的截图,了解如何创建 gh-pages 分支)
Create gh-pages branch
一旦你创建了 gh-pages 分支,github 会自动为你创建一个网站。如果你在你的 github 储存库(“github repo”)上点击“设置”,就会显示你的站点已经发布。例如,如果下面的屏幕截图显示了我的站点在 github repo 中的发布位置:
Your site is published!
如果我点击这个链接,它会显示一个简单的网页。
您现在已经建立了一个发布幻灯片的网站。在接下来的步骤中,我们将使用 git repo 为我们的计算机(可以是本地计算机、实例或虚拟机)创建一个文件夹,我们将在其中构建幻灯片所需的文件。以下是步骤:
第五步 。现在,在您的终端上,“克隆”git repo。首先,做一个目录(或者文件夹)。比如我做了一个名为“jupyterslides”的目录。我从当前目录切换到此目录(1)。然后初始化 git 文件夹(2)。之后,将 github repo 作为子文件夹添加到这个文件夹中(3)。您将看到添加了一个文件夹,其名称与您的 github repo 名称相同。
~$ cd jupyterslides (1)
~$ git init (2)
~$ git submodule add <your github https repo address> (3)
启动 Jupyter 笔记本/Jupyter 实验室并添加内容
第六步 。现在您已经设置了 github repo,并且已经将该 repo 作为子模块添加到您的计算机或实例中,让我们开始构建幻灯片的内容。当您完成本教程时,您将从 Jupyter 笔记本中构建一个简单的演示文稿,并在 web 上显示。稍后,您将看到您可以为该演示文稿构建交互性以及更多高级功能。与 Keynote、Powerpoint 或 OpenOffice/LibreOffice Impress 不同,您将不会使用任何基于点击的系统来构建此类内容;相反,您将使用纯文本工具来构建演示文稿。因此,
- 第一步是开发 Jupyter 笔记本中的内容。
- 第二步是以编程方式将该笔记本转换为降价文档
- 第三步是使用’ pandoc '(一种通用文档转换器,也称为文档转换的瑞士军刀)将文档转换为一组幻灯片
- 第四步是将内容“推送”到 github repo,以便在互联网上显示
第七步 :在 Jupyter 笔记本中创建内容。—对于本教程,让我们创建一个包含五张幻灯片的演示文稿(这是为了演示),其中包含:
- 标题幻灯片(我们稍后将添加标题幻灯片)
- 包含项目符号的幻灯片
- 包含图像的幻灯片
- 包含链接的幻灯片
- 包含表格的幻灯片
稍后我将向您展示,您可以使用这四个元素(项目符号、图像、链接和表格)来创建不同类型的演示。我还将向您展示如何为这些元素添加交互性。你可以使用 markdown 或用 R、Python 或 Julia(实际上还有许多其他语言)编写的代码在 Jupyter 笔记本上创建图像和表格。因此,现在是讨论四个相关问题的好时机:如何在 markdown 中创作内容,什么是 reveal.js 以及我们为什么使用它(还有其他问题),以及幻灯片制作指南。
如何在 markdown 中创作内容
Markdown 是一个内容创作系统,设计用于在 web 上编写结构化文档。文档中的以下元素构成了 markdown 语法:
The following is an example of a table written in Markdown and will be rendered as a table in github flavoured markdown| Element of text | Equivalent Markdown syntax |
|--------------------|-----------------------------------|
| Heading levels | Usually with ## |
| First level header | # Example of a first level header |
| Second level header| ## Second level header |
| Paragraphs | Text separated by two line spaces |
| Unnumbered list | * this is an element |
| Numbered list | 1\. This is the first element |
| Tables | This is a markdown table |
| Formula | $\formula$ |
| Images |  |
| Hyperlinks | [Link text](URL to be linked) |
| References | [@bibtex_entry_ID] |
| Codes | backticks (`code goes here`) |
| Italic | *text to be italicised* |
| Bold | **text to be in bold font** |
| Underline | _text to be underlined_ |
| Blockquote | > Text to be blockquoted |
在上面的代码块中,我已经为您提供了一个常用的降价惯例列表。关于 github 风味减价的更长列表和备忘单,参见以下链接
Google Chrome、Firefox 和 Thunderbird 扩展,可以让你用 Markdown 编写电子邮件,并在发送前呈现。…
github.com](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)
在 Jupyter 笔记本中,您可以在 markdown 中创作文档。Jupyter 笔记本使用 github flavoured markdown,这也是我们将使用的。此外,如果您想使用参考文献和引文,并且如果您想将文档转换为包含引文和参考文献列表的其他格式,我建议您使用 pandoc 将文档从 markdown 格式转换为所需格式。您可以在此了解更多关于 pandoc 以及如何使用 pandoc 传输文档的信息。以下 youtube 视频为您提供了更多关于 pandoc 的信息:
How to use pandoc, a video you can use to learn more about pandoc
我们将在本文档的单独一节中讲述如何使用 pandoc 创建幻灯片。现在,我们将使用 markdown 来编写幻灯片。我们将使用 next reveal.js 来设计我们的幻灯片。
什么是 reveal.js,为什么你会使用它
将 reveal.js 视为一个工具,您将使用它来呈现您创建的幻灯片。Revealjs 由三个元素组成:
- CSS(呈现文档外观的级联样式表)
- javascript 引擎(呈现幻灯片),以及
- 您将创建的 HTML5 文档将显示为幻灯片
考虑您将展示的包含在<section> and \<section>
元素中的每张“幻灯片”。所以,事情是这样的:
<html>
CSS statements
<section>
Your slide data will go here ...</section>
<javacript file>
</html>
这是基本结构。还有其他工具和框架,请查看。在本教程中,我们将介绍 revealjs,在后续教程中,我将介绍其中的几个。一些常见和流行的框架是:
- Impress.js
- Shower.js
- Deck.js
- Remarkjs (我们将在下一个教程中介绍这一点)
我将在随后的帖子中涉及这些,所以这是我们将重点关注 revealjs 的一个帖子。
要让 revealjs 正常运行,您需要做些什么
第八步 。从他们的 github repo 中获取一份 reveal.js 的副本,并在 Jupyter 笔记本的终端中使用 wget 命令,如下所示:
~$ cd myjupyterslides (1)
~$ wget [https://github.com/hakimel/reveal.js/archive/master.zip](https://github.com/hakimel/reveal.js/archive/master.zip) (2)
~$ unzip master.zip (3)
# this will create a folder named 'reveal.js-master'
# rename the folder to 'revealjs' with:
~$ mv reveal.js-master revealjs (4)
对上述代码块的解释:
- 光盘 myjupyterslides (1)。—您将更改目录以进入 myjupyterslides,其中 myjupyterslides 是您之前创建的 github 存储库,因此当您添加 git 子模块时,它将作为文件夹添加到您当前的目录中
- wget (2) wget 是一个帮助您下载 web 内容的实用程序,在这里是 revealjs 存储库的主分支
- unzip master.zip (3)是不言自明的,它将解压文件并在当前目录中添加一个文件夹“reveal.js-master”
- mv reveal.js-master revealjs 是一种“重命名”文件夹的方法,所以现在你的文件夹被重命名为 revaljs。
在这一步的最后,您将使用 revealjs 创建幻灯片的本地副本。但是在我们开始整理内容之前,让我们学习一些关于创建幻灯片和数据可视化的良好实践。这是我将在本系列的后续文章中讨论的内容的高度浓缩版本,但将服务于本教程的目的。
关于创建幻灯片和数据可视化的说明
关于创建幻灯片和数据可视化的一些事情是有序的。
首先,牢记数据墨水五定律从爱德华·塔夫特,
- 最重要的是,展示数据
- 最大化数据油墨比率(每个油墨流更多数据)
- 擦除非数据墨迹
- 擦除多余的数据墨迹
- 修订和编辑
有关上述概念的更详细解释,请查阅以下资料:
“最重要的是,展示数据。”
medium.com](https://medium.com/plotly/maximizing-the-data-ink-ratio-in-dashboards-and-slide-deck-7887f7c1fab)
其他一些技巧包括:
- 编一个有开头、中间和结尾的故事
- 使用故事板来发展你的想法(参见 Garr Reynolds 和 Cliff Atkinson 的作品)
如何使用 Jupyter 笔记本从数据中绘制图表、曲线图和表格
让我们在 jupyter 笔记本中创建一个简单的五张幻灯片演示文稿。语法很简单,我们将创建如下的东西(你可以通过访问这个链接看到它看起来像一个 jupyter 笔记本)
## This is the first slide (1)
- We will create simple set of slides
- Let's analyse some data
- Create a figure from the data
- Create a tablelibrary(tidyverse) (2)mtcars1 <- mtcars %>% (3)
head()
mtcars1 # produces the first five rows in the form of a tablemtcars %>% (4)
ggplot(aes(x = disp, y = mpg)) +
geom_point() +
geom_smooth(method = "loess", colour = "blue", se = FALSE) +
geom_smooth(method = "lm", colour = "red", se = FALSE) +
labs(x = "Engine size",
y = "Miles per gallon",
title = "Relationship between engine size and milage for cars") +
theme_bw() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank()) +
ggsave("test5.png")
上述代码的解释:
(1)这是记录在降价模块中的第一张幻灯片。你可以移动这些块,这样你就可以在 Jupyter
中构建一个故事板(2)这是在代码窗口中编写的,并调用 R
中的 tidyverse 库(3) mtcars1 是从 mtcars 创建的数据子集,这是一个关于汽车的大型数据集;我们将使用它来演示以编程方式创建表格
(4)我们使用此代码以编程方式生成一个图
第九步 。在我们使用 jupyter notebook 和在 jupyter notebook 中使用 R 生成这些图形和表格之后,我们将这个 Jupyter notebook 导出到 markdown 文档中。我们可以使用 jupyter notebook 本身来创建一组 reveal.js 幻灯片,但是首先导出到 markdown 会让您对幻灯片创建元素的某些方面有更多的控制。使用以下代码将 jupyter 笔记本转换为 markdown 文档:
~$ jupyter nbconvert -t markdown mynotebook.ipynb (1)
# generates mynotebook.md (2)
解释:
(1) mynotebook.ipynb 是我要转换的 jupyter 笔记本的名称
(2)这将生成 mynotebook.md markdown 文档
现在我们的减价文件看起来如下:
## This is the first slide
- We will create simple set of slides
- Let's analyse some data
- Create a figure from the data
- Create a table```R
library(tidyverse)
```── [1mAttaching packages[22m ─────────────────────────────────────── tidyverse 1.2.1 ──
[32m✔[39m [34mggplot2[39m 3.1.1 [32m✔[39m [34mpurrr [39m 0.3.2
[32m✔[39m [34mtibble [39m 2.1.3 [32m✔[39m [34mdplyr [39m 0.8.1
[32m✔[39m [34mtidyr [39m 0.8.3 [32m✔[39m [34mstringr[39m 1.4.0
[32m✔[39m [34mreadr [39m 1.3.1 [32m✔[39m [34mforcats[39m 0.4.0
── [1mConflicts[22m ────────────────────────────────────────── tidyverse_conflicts() ──
[31m✖[39m [34mdplyr[39m::[32mfilter()[39m masks [34mstats[39m::filter()
[31m✖[39m [34mdplyr[39m::[32mlag()[39m masks [34mstats[39m::lag()```R
mtcars1 <- mtcars %>%
head()
mtcars1 # produces the first five rows in the form of a table
```<table>
<caption>A data.frame: 6 × 11</caption>
<thead>
<tr><th></th><th scope=col>mpg</th><th scope=col>cyl</th><th scope=col>disp</th><th scope=col>hp</th><th scope=col>drat</th><th scope=col>wt</th><th scope=col>qsec</th><th scope=col>vs</th><th scope=col>am</th><th scope=col>gear</th><th scope=col>carb</th></tr>
<tr><th></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th></tr>
</thead>
<tbody>
<tr><th scope=row>Mazda RX4</th><td>21.0</td><td>6</td><td>160</td><td>110</td><td>3.90</td><td>2.620</td><td>16.46</td><td>0</td><td>1</td><td>4</td><td>4</td></tr>
<tr><th scope=row>Mazda RX4 Wag</th><td>21.0</td><td>6</td><td>160</td><td>110</td><td>3.90</td><td>2.875</td><td>17.02</td><td>0</td><td>1</td><td>4</td><td>4</td></tr>
<tr><th scope=row>Datsun 710</th><td>22.8</td><td>4</td><td>108</td><td> 93</td><td>3.85</td><td>2.320</td><td>18.61</td><td>1</td><td>1</td><td>4</td><td>1</td></tr>
<tr><th scope=row>Hornet 4 Drive</th><td>21.4</td><td>6</td><td>258</td><td>110</td><td>3.08</td><td>3.215</td><td>19.44</td><td>1</td><td>0</td><td>3</td><td>1</td></tr>
<tr><th scope=row>Hornet Sportabout</th><td>18.7</td><td>8</td><td>360</td><td>175</td><td>3.15</td><td>3.440</td><td>17.02</td><td>0</td><td>0</td><td>3</td><td>2</td></tr>
<tr><th scope=row>Valiant</th><td>18.1</td><td>6</td><td>225</td><td>105</td><td>2.76</td><td>3.460</td><td>20.22</td><td>1</td><td>0</td><td>3</td><td>1</td></tr>
</tbody>
</table>```R
mtcars %>%
ggplot(aes(x = disp, y = mpg)) +
geom_point() +
geom_smooth(method = "loess", colour = "blue", se = FALSE) +
geom_smooth(method = "lm", colour = "red", se = FALSE) +
labs(x = "Engine size",
y = "Miles per gallon",
title = "Relationship between engine size and milage for cars") +
theme_bw() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank()) +
ggsave("test5.png")
```Saving 6.67 x 6.67 in image```R```
第十步。 我们将使用以下两个文档中的提示和原则来编写本文档,并使其“值得滑动”:
- Reveal.js 文档(参见 https://github.com/hakimel/reveal.js#markdown):从这个文档中,这几行对我们很有用:
It's possible to write your slides using Markdown. To enable Markdown, add the data-markdown attribute to your <section>elements and wrap the contents in a <textarea data-template> like the example below. You'll also need to add the plugin/markdown/marked.js and plugin/markdown/markdown.js scripts (in that order) to your HTML file.<section data-markdown>
<textarea data-template>
## Page title
A paragraph with some text and a [link](http://hakim.se).
</textarea>
</section>
我们会看到潘多克会为我们做到这一点。但是文件还在继续,
Special syntax (through HTML comments) is available for adding attributes to Markdown elements. This is useful for fragments, amongst other things.<section data-markdown>
<script type="text/template">
- Item 1 <!-- .element: class="fragment" data-fragment-index="2" -->
- Item 2 <!-- .element: class="fragment" data-fragment-index="1" -->
</script>
</section>
这部分需要解释一下。在这里,revealjs 开发人员将您的注意力引向您决定包含在幻灯片中的“降价元素”,并给出了一个列表元素的示例。还有其他元素(注意上面的列表)。你可以用这些类定义来控制每一个元素。但接下来会有一些关于幻灯片组中所有幻灯片行为的问题。这是他们谈论控制元素的地方,比如改变背景颜色,添加一个背景图片而不是一个有标题的图片,等等。以下是相关文档:
Slide AttributesSpecial syntax (through HTML comments) is available for adding attributes to the slide <section> elements generated by your Markdown.<section data-markdown>
<script type="text/template">
<!-- .slide: data-background="#ff0000" -->
Markdown content
</script>
</section>
我们将在本系列的后面部分利用这些信息来生成具有交互性的漂亮幻灯片。现在,我们会让 Pandoc 产生它能产生的东西。以下是 pandoc 文档中的更多信息:
- 关于创建幻灯片组的 Pandoc 文档(参见https://pandoc . org/manual . html # producing-slide-shows-with-pandoc)
从 pandoc 文档中,请注意:
By default, the *slide level* is the highest heading level in the hierarchy that is followed immediately by content, and not another heading, somewhere in the document. In the example above, level-1 headings are always followed by level-2 headings, which are followed by content, so the slide level is 2\. This default can be overridden using the [--slide-level](https://pandoc.org/MANUAL.html#option--slide-level) option.The document is carved up into slides according to the following rules:
* A horizontal rule always starts a new slide.
* A heading at the slide level always starts a new slide.
* Headings *below* the slide level in the hierarchy create headings *within* a slide.
* Headings *above* the slide level in the hierarchy create “title slides,” which just contain the section title and help to break the slide show into sections. Non-slide content under these headings will be included on the title slide (for HTML slide shows) or in a subsequent slide with the same title (for beamer).
* Headings *above* the slide level in the hierarchy create “title slides,” which just contain the section title and help to break the slide show into sections. Non-slide content under these headings will be included on the title slide (for HTML slide shows) or in a subsequent slide with the same title (for beamer).
* A title page is constructed automatically from the document’s title block, if present. (In the case of beamer, this can be disabled by commenting out some lines in the default template.)
遵循这些规则,就有可能构建一系列幻灯片,这些幻灯片可以根据我们的大多数需求进行修改。在本教程中,我们将创建一组简单的幻灯片,因此我们不会深入研究不同的选项。在随后的文章中,我们将探索多种方式来“调整”幻灯片的外观,并为幻灯片添加交互性。
这里,简而言之,至少:
- 我们将添加一个标题页
- 我们将插入一些滑动分隔器
- 我们将删除代码块
在这些更改完成后,最终的 markdown 文档如下所示:
--- (1)
title: A first simple slide deck
author: Me Myself
date: 9th August, 2019
---## This is the first slide (2)
- We will create simple set of slides
- Let's analyse some data
- Create a figure from the data
- Create a table---------- (3)
<table>
<caption>A data.frame: 6 × 11</caption>
<thead>
<tr><th></th><th scope=col>mpg</th><th scope=col>cyl</th><th scope=col>disp</th><th scope=col>hp</th><th scope=col>drat</th><th scope=col>wt</th><th scope=col>qsec</th><th scope=col>vs</th><th scope=col>am</th><th scope=col>gear</th><th scope=col>carb</th></tr>
<tr><th></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th><th scope=col><dbl></th></tr>
</thead>
<tbody>
<tr><th scope=row>Mazda RX4</th><td>21.0</td><td>6</td><td>160</td><td>110</td><td>3.90</td><td>2.620</td><td>16.46</td><td>0</td><td>1</td><td>4</td><td>4</td></tr>
<tr><th scope=row>Mazda RX4 Wag</th><td>21.0</td><td>6</td><td>160</td><td>110</td><td>3.90</td><td>2.875</td><td>17.02</td><td>0</td><td>1</td><td>4</td><td>4</td></tr>
<tr><th scope=row>Datsun 710</th><td>22.8</td><td>4</td><td>108</td><td> 93</td><td>3.85</td><td>2.320</td><td>18.61</td><td>1</td><td>1</td><td>4</td><td>1</td></tr>
<tr><th scope=row>Hornet 4 Drive</th><td>21.4</td><td>6</td><td>258</td><td>110</td><td>3.08</td><td>3.215</td><td>19.44</td><td>1</td><td>0</td><td>3</td><td>1</td></tr>
<tr><th scope=row>Hornet Sportabout</th><td>18.7</td><td>8</td><td>360</td><td>175</td><td>3.15</td><td>3.440</td><td>17.02</td><td>0</td><td>0</td><td>3</td><td>2</td></tr>
<tr><th scope=row>Valiant</th><td>18.1</td><td>6</td><td>225</td><td>105</td><td>2.76</td><td>3.460</td><td>20.22</td><td>1</td><td>0</td><td>3</td><td>1</td></tr>
</tbody>
</table>------ (4)
此代码块的解释:
①这是序言。Pandoc 将首先寻找这个块,如果找不到,它将发出警告。包括至少一个标题、日期信息和作者姓名
(2)这是具有两个散列的第一幻灯片组,说明它是第二级标题,并且由于它后面是内容,因此这被认为是基础级 2
(3)将在下一张幻灯片中张贴表格的分隔符
(4)将在下一张幻灯片中张贴图表的分隔符
第十一步。 本文档保存为‘test 5 . MD’。我们现在将使用 pandoc 将这个 markdown 文档转换成 html。为此,我们键入以下代码(假设您位于正确的文件夹中):
~$ pandoc -t revealjs -s -o {output filename.html} {input markdown file name} -V revealjs-url={file or absolute URL}
所以,在我们的例子中:
- pandoc 是程序
- revealjs = revealjs
- 输出文件 name.html = test5.html
- 输入文件名= test5.md
- revealjs-url =。/reveal js(reveal js 所在的文件夹)
因此,我们有:
~$ pandoc -t revealjs -s -o test5.html test5.md -V revealjs-url=./revealjs
如果一切顺利,这将产生 test5.html 文件。
第十二步。** 现在我们将文件夹连接到 git,并将文件夹提交到 github 库。为此,我们:
~$ git checkout -b gh-pages (1)
~$ git add . (2)
~$ git commit -m "added the slide deck files" (3)
~$ git push origin gh-pages (4)
解释:
(1) git checkout 是您用来切换到您之前创建的 gh-pages 分支的命令,该分支允许您托管您的幻灯片
(2) git add。是您用来添加 git 文件夹中所有内容的命令
(3) git commit -m 表示您添加了一个文本来指示您在该点做了什么:这是您的版本控制
(4) git push origin gh-pages 表示您将文件添加到了您的 gh-pages 分支,它们将从该分支发布
如果一切正常,你的网站将在一分钟后上线(有时,需要更长时间,耐心是一种美德)。假设您的用户名是“someusername ”,并且您创建了一个名为“jupyterslidedeck”的 github 存储库,您的站点将位于:
https://someusername.github.io/jupyterslidedeck/test5.html
它将如下所示:
Your first set of deck
摘要
现在,您已经创建了一个幻灯片。这还远远没有完成,因为你会看到表看起来不太好,图中显示了图像,但它可以更好地对齐,等等。你可能还想添加更多的幻灯片,和更多的互动。我们将在本系列的下一篇文章中解决这些问题。因此,至少总结一下我们所做的事情:
- 启动一个包含你的幻灯片的 github 库,比如“我的幻灯片”
- 使用终端将此 github 存储库的子模块添加到您的“实例”或机器(Mac/Linux/Windows)中;这将创建一个名为“myslides”的文件夹
- 将目录(cd)更改为我的幻灯片
- 使用 wget 命令在该文件夹中获取一个 revealjs git repo zip(master . zip)副本,然后使用 unzip 命令解压缩所有内容,然后将 reveal.js 文件夹重命名为 reveal js(可选)
- 在 myslides 文件夹中启动一个 jupyter 笔记本文件,并编写带有图表、表格、列表和文本的幻灯片文档
- 使用
jupyter nbconvert --to markdown
将 ipynb 文件转换为 markdown 文件格式 - 在 Jupyter 中打开生成的 markdown 文件,添加标题块,添加分隔符,删除(或者您可以保留)代码块等等
- 使用 pandoc 通过
pandoc -t revealjs -s -o whatever.html whatever.md -V revealjs-url=./revealjs
将降价文件转换成 html - 当然,第 8 步假设 whatever.md 是您的 markdown 文件名,revealjs 是您从 revealjs git repo 下载并解压缩 master.zip 文件的文件夹
- 现在切换到 gh-pages 分支,将文件添加到 git repo,提交更改,并推送到您的 git repo。您的幻灯片将会实时播放
从现在起,对幻灯片的任何更改,您可以直接在 markdown 文件中进行,也可以在 jupyter 笔记本中进行,然后重新运行上面列表中的步骤 6 到 10。
如何从列值列表中创建多个工作表,并使用 R 和 VBA 自动删除任何空列
有时候,我们会面临一些我们认为非常容易解决的问题,但实际上在现实生活中并不那么容易。两个很好的例子是根据单元格值将一个大的工作表拆分成多个工作表,并为每个工作表删除大量的空列。让我更详细地解释给你听。
有哪些问题?
假设我们收到了一个这样的文件,并希望基于系列值创建多个工作表。共有 189 种不同的家庭价值观。手动执行这项任务或使用数据透视表效率不高,可能会导致一些内存问题。为此,我们将使用 R 和 VBA。
此外,在分割工作表后,我们将通过删除任何空列来清理每个工作表。该文件有 1,044 列,有些工作表有超过 100 个不连续的空列。
1。根据列值将一个大工作表拆分成多个工作表
首先,我们导入数据并安装软件包。之后,我们检查 family 列中唯一值的数量,并设置工作目录,这样我们的文件就可以保存在一个地方。
install.packages('dplyr')
library(dplyr)#importing the file
demo <- read.csv("C:/Users/kewon-de/Desktop/tbd/demo.csv.txt", sep=";")#checking the # of values in the family column
length(unique(demo[["family"]])) #189# setting the working directory
setwd("C:/Users/kewon-de/Desktop/tbd")
使用下面的 R 代码,我们可以根据列值快速创建多个工作表。该程序循环遍历列值(=族)列表,并创建多个数据框。这些数据框以后会变成工作表。
for(i in (demo$family)) {
name <- paste("demo", i, sep = ".")
assign(name, demo[demo$family==i,])
}
data frames with empty columns
2。删除任何空列
创建数据框后,我们现在可以检查是否有任何空列。首先,我们应该将所有数据帧放入一个列表中,这样我们就可以对列表应用一个函数(一次对所有数据帧应用函数)。下面的函数将去掉只有 na、null、无信息和 0 的列。在此之后,我们可以解压缩数据帧并验证列的数量——空列是否被正确删除。
lst<- mget(ls(pattern='^demo')) # putting 'demo' dataframes into a listoutput <- lapply(lst, function(df) Filter(function(x)!all(is.na(x) || is.null(x) || x == "" || x == 0),df))list2env(output,envir=.GlobalEnv)#unzipping the list
在清理空列之前,有 1044 列。
list of data frames before cleaning the empty columns
清理后,数据帧的数量变为 13 至 19 列。
list of data frames after cleaning the empty columns
clean data frames with no empty columns
解压缩列表时,干净的数据帧会替换旧的数据帧,如上所示。
- 如果只想移除几个数据框的空列,可以使用此代码手动完成。
demo.acc_consoles <- Filter(function(x)!all(is.na(x) || is.null(x) || x == "" || x == 0), demo.acc_consoles)
3.将干净的数据帧导出为 CSV 格式
既然所有的数据帧都是干净的,我们可以使用下面的代码将它们导出为 CSV 文件。
install.packages("xlsx")
library(xlsx)
for(i in names(output)){
write.xlsx(output[[i]], paste0(i,".xlsx"),sheetName = i)
}
下面是在 r 中曾经是数据帧的 CSV 文件。
data frames in CSV
4.将 Excel 文件合并成一个文件
文件夹里有多个 excel 文件就没那么方便了;我们不能浏览产品。让我们用 VBA 把所有的 excel 文件合并成一个,这样我们就不用一次又一次地打开文件了。
在 excel 中,进入文件,点击选项,添加开发者。
当 VBA 屏幕弹出时,右击 Sheet1 并插入模块。
当模块弹出时,在屏幕上插入以下代码,并单击绿色箭头按钮运行代码。不要忘记添加您自己的 excel 文件所在的路径。
Sub GetSheets()
Path = "insert your own path here"
Filename = Dir(Path & "*.xls")
Do While Filename <> ""
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
For Each Sheet In ActiveWorkbook.Sheets
Sheet.Copy After:=ThisWorkbook.Sheets(1)
Next Sheet
Workbooks(Filename).Close
Filename = Dir()
Loop
End Sub
module
运行代码时,文件夹中的 excel 文件会自动合并成一个。
最后,我们有一个包含 189 个工作表的 excel 文件,中间没有空列。
本文分为两个部分:1)如何基于列值创建多个工作表 2)如何删除不连续的空列。您可以根据自己的需要简单地选择一个部分。
谢谢你看我的文章!如果你喜欢我所做的,不要犹豫,在 GitHub 上关注我,在 Linkedin 上与我联系。
另外,请随意查看我的其他文章:
如何获得关于货币汇率的 Twitter 通知:网络抓取和自动化
如何从头开始创建 NumPy 数组?
本教程是关于理解 NumPy python 包和从头开始创建 NumPy 数组的。
Credits: GitHub
不管数据如何,分析它们的第一步是将它们转换成一组数字。有效地进行数据科学的基本过程是存储和操作数值数组。因此 Python 有专门的工具来处理数字数组:
- NumPy 包
- 熊猫套餐
本教程只关注 NumPy 包。然而,熊猫包装文件将在晚些时候提供。教程的完整代码可以在下面我的 GitHub 库 中找到:
此时您不能执行该操作。您已使用另一个标签页或窗口登录。您已在另一个选项卡中注销,或者…
github.com](https://github.com/Tanu-N-Prabhu/Python/blob/master/How_to_create_NumPy_arrays_from_scratch%3F.ipynb)
什么是 NumPy?
NumPy 代表 数值 Python。 NumPy 提供了一种高效的方式来存储和操作密集数据缓冲区。在 NumPy 库的帮助下,我们可以创建和操作数组来存储数据。在某些方面,NumPy 的数组就像 Python 的 list 内置函数。
如何执行 NumPy 并检查其版本?
让我们开始吧。你可以在你喜欢的 python 编辑器中执行下面的程序,比如 PyCharm , Sublime Text ,或者笔记本比如 Jupyter 和 Google Colab 。选择一个你喜欢的 IDE 基本上是你的喜好。我使用 Google Colab 来编写我的代码,因为它给了我大量的选项来提供好的文档。此外,请访问 NumPy 网站 以获得有关安装过程的更多指导。
一旦在 IDE 上安装了 NumPy,就需要导入它。检查库的版本通常是一个好习惯。所以要安装 NumPy 库,你需要使用下面的代码。
import numpy
print(numpy.__version__)**1.17.4**
只要确保你是最新的 NumPy 版本就可以使用所有的功能和选项。与其用"【numpy】“我们可以用一个别名作为”【NP"。这就是所谓的“ 走样 ”。现在使用别名的要点是我们可以使用" np “而不是” numpy ",每次使用它的方法时都需要键入很长的时间。因此,创建别名并检查版本可以如下所示:
import numpy as np
print(np.__version__)**1.17.4**
从现在起,我们每次都可以用“ np ,而不是“ numpy ”。
为什么有了 python 的固定类型数组,Numpy 数组就出现了?
Python 提供了几种不同的选项来存储高效的固定类型数据。Python 有一个内置的数组模块叫做“ array ,用来创建统一类型的数组。这是它的主要缺点。
import array# Creating an array
print(array.array('i', [1, 2, 3, 4, 5]))**array('i', [1, 2, 3, 4, 5])**
这里的“ i ”表示整数数据。我们不能尝试在数组模块中存储其他类型的数据。这通常会导致错误。
import array# Creating an array
print(array.array('i', [1, 2.0, 3, 4, 5]))**--------------------------------------------------------------------****TypeError Traceback (most recent call last)**[**<ipython-input-25-49d63cb1f570>**](/<ipython-input-25-49d63cb1f570>) **in <module>()
----> 1 array.array('i', [1, 2.0, 3, 4, 5])****TypeError: integer argument expected, got float**
然而,Python 的数组模块提供了基于数组的数据的高效存储。但是 NumPy 数组可以对这种类型的数据执行有效的操作。有两种方法可以创建 NumPy 数组:
- 从 Python 列表创建 NumPy 数组
- 从头开始创建 NumPy 数组
从 Python 列表创建 NumPy 数组
我们可以使用NP . array方法从 python 列表中创建数组。
import numpy as np# Creating a list named "a"
a = [1, 2, 3, 4, 5]
print(type(a))**<class 'list'>**# Creating a numpy array from the list
print(np.array(a))**[1 2 3 4 5]**print(type(np.array(a)))**<class 'numpy.ndarray'>**
NumPy 库仅限于具有相同类型的数组,如果存在类型不匹配,则可能的话会向上转换。考虑下面的例子:
import numpy as np# Creating a list named "a"
a = [1, 2.0, 3, 4, 5]
print(type(a))**<class 'list'>**# Creating a numpy array from the list
print(np.array(a))**[1\. 2\. 3\. 4\. 5.]**print(type(np.array(a)))**<class 'numpy.ndarray'>**
因此,原来的列表是具有一个浮点值的整数,但是 numpy 数组将其向上转换为所有的 浮点数 。整数被向上转换为浮点数。下面是一个小图表,给你足够的知识来理解向上转换和向下转换。
Numpy upcast and downcast
显式设置数据类型也是可能的。这可以使用关键字“ dtype ”来完成。
import numpy as np# Creating a list named "a"
a = [1, 2, 3, 4, 5]# Creating a numpy array from the list
np.array(a, dtype='float64')print(np.array(a, dtype='float64'))**[1\. 2\. 3\. 4\. 5.]**
从上面的例子可以看出,通过使用关键字“ dtype ”将整数类型的列表数据转换为浮点类型的数据。
Numpy 数组也可以是 多维的(数组中的数组)。这是做这件事的一种方法。
import numpy as np# Creating a list named "a"
a = [1, 2, 3, 4, 5]# Creating a numpy array from the list
np.array([range(i, i + 4) for i in a])**[[1 2 3 4]
[2 3 4 5]
[3 4 5 6]
[4 5 6 7]
[5 6 7 8]]**
提示 :只需将“I”的值递增 1 (i+1,2,3,4,…)这样做也可以增加数组的维数。上述阵列被视为 2D 阵列。
从头开始创建 NumPy 数组
Numpy 数组实际上用于创建更大的数组。使用 numpy 包库从头开始创建大型数组效率更高。下面是一些从头开始创建 numpy 数组的例子。
- 创建一个长度为 5 的零填充的数组
我们可以使用名为 零 的 numpy 内置方法来实现这一点,如下所示:
import numpy as np# Creating a numpy array of zeros of length 5
print(np.zeros(5, dtype='int'))**[0 0 0 0 0]**
有一些标准的 numpy 数据类型可用。我不能一口气讨论所有的问题。大部分都没用过。所以我将以图表的形式提供 numpy 数组的数据类型。如果你不知道如何使用数据类型,请参考显式更改其上面的数组数据类型→dtypes = “数据类型的名称”****
Credits: Python Data Science Hand Book
2。创建一个用 1 填充的 3 x 4 数组
感谢 NumPy,因为我们不必将数组放在循环语句中(我讨厌这样做;)).你所要做的就是在 numpy.one 方法中提到你希望你的数组包含的行和列。
import numpy as np# Creating a numpy array of 1’s which should have 3 rows and 4 columnsprint(np.ones((3, 4)))**[[1\. 1\. 1\. 1.]
[1\. 1\. 1\. 1.]
[1\. 1\. 1\. 1.]]**
所以数字 3 →行和 4 →显然是列。
3。用特定的数字填充 numpy 数组
到目前为止,我们已经看到用 0 和 1 填充数组,但是我们还应该知道 numpy 允许我们用我们选择的任何特定数字填充数组。我们可以借助 numpy.full 方法来做到这一点。例如,让我们用数字 500 填充数组。
import numpy as np# Creating a numpy array of 500’s which should have 3 rows and 4 columnsprint(np.full((3, 4), 500))**[[500 500 500 500]
[500 500 500 500]
[500 500 500 500]]**
在 full 方法的帮助下,我们可以向数组中添加任意数量的元素。
4。创建随机数的 numpy 数组
均匀分布→ 它是所有结果发生的可能性相等的概率分布。例如,投掷硬币的概率是均匀分布的,因为结果很可能是正面或反面。两者不可能同时存在。
NumPy 包库为我们提供了一种生成随机数的均匀分布方法,名为NumPy . random . uniform**。**
import numpy as np# Create a 3x3 array of uniformly distributed
# random values between 0 and 1print(np.random.random((3, 3)))**[[0.89865866 0.71138067 0.85067426]
[0.53568422 0.32887081 0.97449983]
[0.48130729 0.15841703 0.57756513]]**
此外,numpy 包库有一个种子生成器和随机数生成器,在种子方法的帮助下,我们可以控制随机数生成的顺序。他们中的大多数人不知道种子方法的特殊性及其目的。要了解更多关于 seed 方法的信息,请参考下面的内容。
为什么我们需要随机数生成器内部的“种子”?
如果我们每次都使用种子,那么我们会得到相同的随机数序列。
因此,相同的种子产生相同的随机数序列。
import numpy as np# Create a random number arrays of size 5
np.random.seed(0)
print(np.random.random(5))**[0.5488135 0.71518937 0.60276338 0.54488318 0.4236548]**
不管你执行上面的代码多少次,每次你都会得到相同的随机数。要了解区别,只需对代码(#)进行注释,然后查看区别。让我们更深入地研究一下 seed 方法。
例如,如果您使用种子(1),然后生成一些随机数,它们将与您稍后生成的随机数相同,但使用相同的种子(1),如下所示。
import numpy as np# Create a random number arrays of size 5np.random.seed(1)
print(np.random.random(5))**[4.17022005e-01 7.20324493e-01 1.14374817e-04 3.02332573e-01 1.46755891e-01]**print(np.random.random(5))# Different random numbers would be generated now
**[0.09233859 0.18626021 0.34556073 0.39676747 0.53881673]**np.random.seed(1)
print(np.random.random(5))# Same random numbers would be generated same as the first time - Due to seed
**[4.17022005e-01 7.20324493e-01 1.14374817e-04 3.02332573e-01 1.46755891e-01]**
相同的种子相同的随机数保证“再现性”——Quora.com
同样,种子的范围是从 0 到 2 * * 32–1。 不要只使用负数作为种子值,如果你这样做你会得到如下所示的错误:
import numpy as npnp.random.seed(-1)-------------------------------------------------------------------**ValueError Traceback (most recent call last)**[**<ipython-input-9-bfd0c22f2d0a>**](/<ipython-input-9-bfd0c22f2d0a>) **in <module>()
----> 1 np.random.seed(-1)****mtrand.pyx in numpy.random.mtrand.RandomState.seed()****mt19937.pyx in numpy.random.mt19937.MT19937._legacy_seeding()****mt19937.pyx in numpy.random.mt19937.MT19937._legacy_seeding()****ValueError: Seed must be between 0 and 2**32 - 1**
正态分布→ 也称为高斯分布,是一个实值随机变量的连续概率分布。它也被称为一个 对称分布 其中大部分数值集中在峰值的中心。标准差决定了价差。
NumPy 包库为我们提供了一种生成随机数的均匀分布方法,名为NumPy . random . normal**。语法与均匀分布几乎相同,但您需要添加两个更重要的数据,这里称为 均值 和 标准差 。**
import numpy as np# Create a 3x3 array of normally distributed random values
# with mean 0 and standard deviation 1print(np.random.normal(0, 1, (3, 3)))**[[-0.56651023 0.7299756 0.37299379]
[ 0.53381091 -0.0919733 1.91382039]
[ 0.33079713 1.14194252 -1.12959516]]**
5。使用 numpy 数组创建单位矩阵
单位矩阵是这样的矩阵,其中主对角元素是 1,除了主对角元素之外的其他元素是 0。numpy 包库提供了一种生成称为 眼的单位矩阵的方法。 单位矩阵是一个方阵,意思是它有相等的行和列。
import numpy as np# Create a identity matrix of 4 rows and 4 columnsprint(np.eye(4))**[[1\. 0\. 0\. 0.]
[0\. 1\. 0\. 0.]
[0\. 0\. 1\. 0.]
[0\. 0\. 0\. 1.]]**
数字 4 代表行和列,因为它是一个正方形矩阵,我们只需要指定一次该值(本例中为 4)。
本教程到此结束如何从头创建 NumPy 数组?”,这只是 NumPy 包库的入门教程。然而,更复杂的 NumPy 包库的概念将在接下来的教程中讨论。谢谢你们花时间阅读我的教程。我希望你喜欢它。如果你对 NumPy 有任何疑问,那么评论区就是你的了。直到那时再见,看到你有一个美好的一天。
如何使用 gganimate 创建动画精美的剧情?
Total suicide rates per country
引言。
可视化最重要的事情是当它迫使我们意识到一些我们不知道的事情。视觉上吸引人的图表很容易吸引我们的注意力。将数据动画化就像将生命吸入尘埃,这是一种创造的行为。你是如何创作出富有洞察力的吸引人的动画的?
在这篇文章中,我们将学习如何使用 R 包来创建漂亮的动画, gganimate 。
**#stable version of the package can be installed using** *install.packages(“gganimate”)* **#latest development version can be obtained by** *devtools::install_github(“thomasp85/gganimate”)*.
数据。
自杀率数据是从不同来源(世卫组织、联合国开发计划署、世界银行)汇编后从 Kaggle 获得的。该数据比较了 1985 年至 2016 年每个国家的社会经济信息和自杀率。灵感来自于不同国家的自杀预防策略。
数据角力。
我们将使用下面的代码来清理数据,并且只对我们将要处理的列进行子集化。
**#loading required libraries**
library(tidyverse)
library(reshape2)
library(ggthemes)
library(gganimate)
library(gifski)**#loading dataset**
suicide_data<-read.csv("./ARTICLES/suicide rates/master.csv",header = TRUE,stringsAsFactors = FALSE)**#selecting columns to work with**
suicide_sub<-suicide_data %>% select("ï..country","year" ,"sex","suicides_no") %>% rename("country"="ï..country" )**#function to sum the total suicide per country**
n<-unique(suicide_sub$country)
country<-function(x){
suicide2<-suicide_sub %>% filter(country==x)
sum(suicide2$suicides_no)
}**#return a list with all total deaths per country**
country_total<-sapply(n,function(x) country(x))**#creating a dataframe with top 10 total suicides per country**
df<-do.call(rbind,Map(data.frame,Country=n,Total_Suicides=country_total))
df2<-df %>% arrange(desc(Total_Suicides))
df3<-head(df2,n=10)
write.csv(df3,"./ARTICLES/suicide rates/total_suicide.csv")**#plotting the top 10 countries leading in the total suicide rates**
ggplot(df3,aes(reorder(Country,Total_Suicides),Total_Suicides,fill=as.factor(Country)))+
geom_col()+
coord_flip(clip = "off", expand = FALSE)+
guides( fill = FALSE) +
labs(title="TOTAL SUICIDE DEATHS PER COUNTRY FROM 1985-2016",
y="Total Suicides Per Country", x="Country")+
scale_y_continuous(labels = scales::comma) +
geom_text(aes(label = paste(Total_Suicides,"")), hjust = 1)
**#subset initial data with top 10 countries**
top_suicide<-suicide_sub%>%filter(country==c(“Russian Federation”,”United States”,”Japan”,”France”,”Ukraine”,”Germany”,”Republic of Korea”,”Brazil”,”Poland”,”United Kingdom”))**#filtering years with consistent data**
top_suicide2<-top_suicide %>% filter(year %in%c(1990:2014))
top_suicide2$sex<-as.factor(top_suicide2$sex)**#summing the total male & female suicides per country for each year**
sm3<-aggregate(suicides_no~country+year,top_suicide2,sum)**#* 1 ensures we have non-integer ranks while sliding**
sm4<-sm3 %>% group_by(year) %>% mutate(rank = min_rank(-suicides_no) * 1) %>%
ungroup()
构建静态地块。
我们的数据现在已经可以绘图了。我们不打算深入使用 ggplot 的更多细节。使用 ggplot 的综合指南可在这里获得。
**#plotting static plot**
static_plot<-ggplot(sm4,aes(rank,group=country,fill=as.factor(country),color=as.factor(country))) +
geom_tile(aes(y = suicides_no/2,
height = suicides_no,
width = 0.9), alpha = 0.8, color = NA) +
geom_text(aes(y = 0, label = paste(country, “ “)), vjust = 0.2, hjust = 1) +
geom_text(aes(y=suicides_no,label = paste(“ “,suicides_no)), hjust=0)+
coord_flip(clip = “off”, expand = TRUE) +
scale_y_continuous(labels = scales::comma) +
scale_x_reverse() +
guides(color = FALSE, fill = FALSE) +
theme_minimal() +
theme(
plot.title=element_text(size=25, hjust=0.5, face=”bold”, colour=”grey”, vjust=-1),
plot.subtitle=element_text(size=18, hjust=0.5, face=”italic”, color=”grey”),
plot.caption =element_text(size=8, hjust=0.5, face=”italic”, color=”grey”),
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
plot.margin = margin(1,1,1,4, “cm”)
)
动画。
gg animate 的关键特性是什么?
- *transition_ : 此函数定义数据应该如何分布,以及它如何随时间的推移与自身相关联。
a. transition_reveal: 这允许你让数据逐渐消失。
b.**转换时间:**状态之间的转换长度被设置为对应于它们之间的实际时间差。
c. transition_state: 用于通过分类变量或离散变量来激活图形。
- *view_ : 用于定义轴应该如何随动画变化。
a.**view _ follow(fixed _ y = TRUE)😗*这意味着当动画运行时,y 轴是固定的。
b.view _ follow(fixed _ x = TRUE):当动画运行时,x 轴是固定的。
- ease_aes(): 它描述了在动画制作过程中应该如何缓和不同的美感。
a. ease_aes(“立方进制出”)
b. ease_aes(“正弦输入输出”)
- *enter_*/exit_ : 用于确定在动画过程中,新数据如何出现,旧数据如何消失。
a.进入 _ 淡出/退出 _ 收缩
- State_length: 这是指状态暂停的相对长度。
6.**过渡 _ 长度:**这是动画的相对长度。
**#creating final animation**
plt<-static_plot + transition_states(states = year, transition_length = 4, state_length = 1) +
ease_aes(‘cubic-in-out’) +
#view_follow(fixed_x = TRUE) +
labs(title = ‘Total Suicides per Year : {closest_state}’,
subtitle = “Top 10 Countries”,
caption = “Data Source: World Bank Data”,
x=”Countries”,y=”Total Suicides per year”)
7.渲染。
这是一种输出最终结果的计算。使用的参数包括:
nframes: 设置要使用的帧数(默认为 100)。
每秒帧数(fps): 这是每秒每帧花费的时间(默认为 10)
**渲染器:**设置将每一帧合成动画的功能。(默认为 gifski_renderer())。
如果我们想结束循环,我们使用:renderer = gif ski _ renderer(loop = FALSE)为了将动画情节保存为视频,我们使用renderer = ffmpeg _ renderer()
8.持续时间这是帧制作动画所需的总时间,即持续时间=30
9.布局。
我们可以通过指定大小来改变绘图的高度和宽度
我们将动画输出保存到一个名为 final_animation 的对象中。
**#rendering the animation for gif**
final_animation<-animate(plt,100,fps = 20,duration = 30, width = 950, height = 750, renderer = gifski_renderer())**#rendering the animation for mp4** animate(plt,100,fps = 20,duration = 30, width = 950, height = 750, renderer = ffmpeg_renderer())
10。保存动画。
为了保存我们的动画,我们将使用带有参数的函数 anim_save() :
动画——这是我们动画剧情的最终输出。
路径-我们想要保存动画的地方。
**#saving the animation**
anim_save(“./ARTICLES/suicide rates/suicide_animate.gif”,animation=final_animation)
输出。
Final animation output.
结论。
我们已经能够用动画软件包来显示每个国家的自杀率。你可以调整代码,以有效地动画任何数据集,并纳入自己的演示文稿,博客或网站。要获得更多关于创建动画的见解,你可以查看这篇 StackOverflow 指南或关于数据科学的文章。随意评论,分享,点赞。更多讨论,你可以通过 Linkedln 联系我。
如何从头开始创建简单的基于关键词的电影推荐模型
介绍
你试过用电影推荐器吗?理论上,这是一些有用的东西,可以帮助确定下一步该看什么,而不是花几个小时浏览网飞,但他们的结果往往是漫无目的的。这是一个大多数人都会涉及的问题,所以我决定自己创建一个自制的推荐系统,并在这篇博文中分享。我将向您展示如何从头开始创建 3 个简单的推荐模型,接受一部电影作为输入,返回“n”部最相似的电影作为输出,其中“n”由用户提供。
一般来说,推荐系统要么基于内容,要么与用户的历史和兴趣合作。我选择创建基于内容的模型,因为它们基于特定的输入项(电影)而不是基于用户进行预测。
注意,这个博客的推荐完全基于电影关键词。正如您将看到的,使用其他文本信息,如情节大纲或情节概要,而不是电影关键字是相当简单的。
为了限制这篇文章的范围,我没有包括数字特征(例如运行时间、发布年份、评级等。)和流派进行推荐。
如果你想在 GitHub 上关注或查看这篇文章的代码,请访问:https://GitHub . com/gbl inick/Movie-Recommender-with-NLP/blob/master/Keyword % 20 Movie % 20 Recommender . ipynb
数据集创建
任何数据科学项目的第一步都是获取数据集。有时你的数据集会给你(比如 Kaggle 竞赛)。在我们的例子中,由于这个项目是“从零开始”的,我们必须自己获得数据。
寻找电影数据的第一个地方是 https://www.imdb.com/interfaces/的 IMDb 公共数据仓库:。这个存储库包含 7 个表,其中包含各种各样的优秀电影数据。不幸的是,没有一个表格包含我们可以用来推荐的电影关键词。这并不意味着我们不能使用任何表格。看看这些表格,我们注意到其中一个,【title.ratings.tsv.gz】的包含一个名为“numVotes”的列,表示“该标题获得的票数”。这对我们很有用,因为我们可以使用这个列来获得投票数最多的 10,000 部电影。当然,如果能在我们的模型中包含每一部电影就好了,但是由于计算相似性需要额外的时间,这是不实际的。此外,即使我们没有实际的计算缺陷,我也不确定大多数人是否有兴趣看排名前 10,000 以外的电影。前 10,000 部电影应该足以让绝大多数观众满意。
我们还需要第二个表,title.basics.tsv.gz,它提供列标题类型,告诉我们标题是否是电影(相对于电视节目)。因为我们只想在我们的推荐者中包含电影,所以我们使用该列来过滤电影。
综上所述,这是我们目前的工作流程:
- 导入必要的库(熊猫和 numpy):
2.将我们需要的两个 IMDb 表导入 pandas 的数据框架中(在图中,文件位于与我们的笔记本平行的名为“data”的文件夹中):
3.仅从 title.basics 表中选择电影,并创建一个新的数据帧“电影”:
4.为表创建一个公共索引(两个表中每个标题的 IMDb 唯一标识符在这里是一个很好的选择),然后用一个简单的内部连接来连接表:
太好了!我们现在有一个名为“movies_with_rating”的表,其中包含所有 IMDb 电影及其评级(以及我们使用的 2 个表中的所有其他信息)。让我们看看最上面一行:
我们在表格中看到一些关于第一部电影的有趣信息。然而,我们未来的模型并不需要所有这些数据。对于这个项目,我们所关心的是通过 numVotes 获得前 10,000 部电影,并使用电影关键字来查找电影之间的相似性。
我们可以很容易地用熊猫来做到这一点。sort_values 函数:
完美。现在,我们可以将注意力转向获取我们想要用于推荐模型的情节信息。我们可以使用精彩的 IMDbPY API:【https://imdbpy.readthedocs.io/en/latest/index.html】获得这样的剧情信息。您需要使用 pip 或 conda 安装 API。
在使用 API 之前,我们需要导入它并实例化一个 IMDb 电影对象。我们将这样做,并导入几个其他的库,使用 API 运行 for-loops 成为更好的体验:
从 IMDb 提取绘图关键字的语法如下:
在上面的代码中,我首先实例化了一个字典来存储我将从 IMDb(在第 1 行)获取的关键字。我将使用电影 id 作为键,使用每部电影的关键字列表作为值。
在从第 2 行开始的 for 循环中,我遍历了前 10,000 部电影的索引。在第 5 行,我使用每个电影索引来获取相应的 IMDb 电影对象。请注意,在第 5 行,我从索引 2 开始对电影索引进行了子集化,因为索引以“tt”开头,后面跟着一个数字,而我们只需要这个数字。然后,我通过“情节大纲”对电影对象进行子集划分,以获得所需的情节大纲,然后将结果关键字列表作为对应于电影索引键的值存储在我的关键字字典中。
注意我在上面的代码中使用了 tqdm 和 sleep 库。tqdm 允许你看到你在 for 循环运行中的位置。当你运行一个 for 循环 10,000 次时(就像我们一样),很高兴知道你走了多远。
睡眠图书馆让我们对 IMDb 有礼貌。假设我们请求网站给我们 10,000 次信息,最好将我们的请求分隔开,这样我们就不会让服务器不堪重负。
完成 for 循环后,我们有了一个字典,其中的键是电影 id,值是关键字列表。看起来是这样的:
我们应该把这本字典转换成熊猫数据框架,以利用熊猫的能力。但是,如果我们只是做一个简单的 pd。熊猫会抱怨我们的字典长度不一样。因此,我们需要一个解决方案来获得我们想要的东西,如下面的代码所示:
在第 1 行中,我们创建了一个新的字典,其中有相同的键,但值与之前的字典不同。这些值不再是关键字列表,而是熊猫系列。我们可以将这个字典转换成 DataFrame,然后在第 10 行用一个简单的 lambda 函数连接所有的关键字(现在是它们自己的列)。应用 lambda 函数后,我们得到一个系列,因此我们可以将这个系列转换为 DataFrame,重命名我们的列,并保存为 CSV。
我们不需要将绘图轮廓保存到 CSV 文件中,但是当您从一个耗时的过程中获取数据时,保存它是非常明智的,这样您就不必重新运行获取数据的过程。
要使用我们的绘图轮廓数据,我们可以从 keywords.csv 文件中加载它,重命名文件中存在的 2 列(即键和值)并将其连接到我们现有的表中:
就是这样!
我们现在有了一个情节文本信息的数据集,可以用来计算电影之间的相似性。
电子设计自动化(Electronic Design Automation)
在创建我们的模型之前,让我们做一些快速的 EDA。文本数据不是最容易进行探索性数据分析的数据,所以我们将保持 EDA 简短。
我们可以做的第一件事是查看每个关键字列表中字符数量的分布。我们先剔除没有关键词的电影:
我们现在可以找到每个关键字列表的长度(以字符为单位):
从分布和每列的平均字符数可以看出,分布是右尾的。
让我们看看,如果我们为每个关键字列表中的单词数绘制分布图,是否会得到类似的分布:
是的,也很右尾。
因此,我们对关键词列表进行了两种不同的测量——列表中的字符数和单词数——它们显示了相同的模式。这是有意义的,因为这些度量是直观相关的。右翼告诉我们的是,大多数电影没有很多关键词或角色,但有一小部分——大概是最成功的电影——有很多关键词和角色。
创建模型
我们现在可以创建我们的模型了。首先,我想讨论一个关于自然语言处理和使用文本的问题。通常,当使用文本时,你没有好的、易于使用的关键字列表。如果我们决定使用情节概要而不是关键词列表(如果 IMDb 不提供电影关键词,就会发生这种情况),我们就会遇到这种情况。在这种情况下,有一些标准的,简单的步骤,你可以采取,以基本上创建自己的关键字列表。它们是:
1.小写单词
2.删除标点符号
3.删除停用词
4.词汇词条化
这些都可以使用 nltk 库相对简单地完成。
回到我们的模型:我们将创建 3 个不同的模型,基于不同的相似性概念以及不同的电影文本“向量”公式。前 2 个模型将使用余弦相似度,最后一个将使用 Jaccard 相似度。在前两个模型中,第一个将使用 tf-idf 创建电影矢量,第二个将使用简单的字数统计。
我们首先选择我们需要的列。因为我们正在创建基于关键字的推荐器,所以我们需要 keywords 列。因为我们还想输入一部电影的标题并获取其他电影,所以我们需要“primaryTitle”列。因此,我们将选择这两列。我们还重置了索引,因为我们的推荐功能稍后将使用电影在数据帧中的位置,而不是其 IMDb ID 来进行推荐:
接下来,我们需要获得一个列表列表,其中内部列表是每部电影的关键字列表。目前,我们在每部电影的关键字列中有一个字符串,其中包含所有关键字,并用逗号分隔。
我们可以通过使用 nltk 库获得这样一个列表列表:
在第 2 行,我们得到了前面提到的字符串列表。在第 4 行,我们从 nltk 库中导入了 work_tokenize 模块。在第 5 行,我们有一个列表理解,我们循环遍历每个关键字串,对于每个关键字串,我们得到带有 word_tokenize 的单个单词。注意*word _ token ize(keyword . lower())*返回一个关键字列表,所以我们最终得到一个列表的列表。
我们在这一点上还没有完成,因为 word_tokenize 在我们的关键字列表中留下了许多逗号。我们可以通过定义一个自定义函数 no_commas ,并将其应用于我们的关键字列表列表中的每个关键字列表,来轻松摆脱它们:
很好。所以我们现在在 processed_keywords 中有了我们想要的东西。
我们现在可以创建我们的第一个模型,一个使用词向量间余弦相似度的 tf-idf 模型。我不打算在这里解释它们是如何工作的。快速的谷歌搜索应该会返回许多有用的资源。
我们首先使用 gensim 创建一个单词字典:
这里的字典只包含我们处理过的关键字列表中与 ID 匹配的每个单词。
接下来,我们创建一个 genism 语料库,这里的语料库只是指“每部电影的词汇包”:
接下来,我们可以使用 genism tf-idf 模型将这些单词包转换为 tf-idf 模型:
最后,我们为我们的电影关键字集创建一个索引,允许我们计算任何给定的关键字集与我们的数据集中每部电影的关键字之间的相似性:
我们现在可以写一个函数来接受一部电影,并返回“n”部最相似的电影。我们函数的工作方式如下:
1.接受用户的电影
2.接受来自用户的“n ”,其中“n”是用户想要返回多少部电影
3.检索电影的关键词
4.将电影的关键词转换成单词包
5.将单词袋表示转换成 tf-idf 表示
6.使用 tf-idf 表示作为查询文档来查询我们的相似性度量对象
7.获取我们集合中每部电影的相似性结果,按照相似性递减的方式对集合进行排序,并返回“n”部最相似的电影及其相似性度量。不要返回最相似的电影,因为每部电影都是最相似的
在代码中:
现在让我们来测试一下。因为复仇者联盟最近很受欢迎,所以让我们将原始电影交给我们的功能:
看起来都很般配。
请注意,这种推荐系统不仅限于根据其他电影推荐电影。我们可以使用任何给定的关键字集来查询我们的相似性度量对象。碰巧的是,大多数人会想使用他们已经知道的电影来查询它,但它不限于此。
以下是基于提供的关键词进行推荐的更通用的函数:
我们可以继续我们的第二个推荐器,它也使用余弦相似度来计算单词向量之间的相似度。它与第一个模型的不同之处在于使用更简单的字数,而不是创建 tf-idf 字向量。这个替代实现是用 scikit-learn 中的 CountVectorizer 类来执行的,它将一组文本文档(在本例中是关键字列表)转换成一个令牌计数矩阵。
为了简单起见,我们还将计算余弦相似度。我们将使用 scikit-learnmetrics . pairwise子模块中的余弦相似度函数,而不是使用矩阵相似度。
我们用下面的代码计算每部电影的字数:
然后,当给定一部电影时,我们需要做的就是计算该电影的词向量和其他词向量之间的余弦相似度,并返回最相似的匹配。这是通过我们的余弦推荐器功能实现的:
让我们在《复仇者联盟》中也尝试一下:
有用!与第一个模型相似。
对于我们的第三个模型,我们使用 Jaccard 相似度代替余弦相似度。因此,我们根本不需要单词向量。我们简单地将相似性计算为关键字集的交集除以关键字集的并集。
计算任意两个关键字列表之间的 Jaccard 相似性的代码很简单:
由此创建推荐器模型相对简单。我们找到给定的输入电影的关键字列表,计算该列表和每个其他电影关键字列表之间的 Jaccard 相似性,然后根据它们的相似性对电影进行排序,并返回前“n”个结果。
在代码中:
用我们最喜欢的电影进行测试,我们得到了很好的结果:
后续步骤
我们有很多方法可以改进现有的模型。
首先是用 Flask 部署模型,这样人们就可以使用它们了。可用性非常重要。
下一步将是找到一些方法来衡量我们的模型的性能。这很棘手,因为推荐系统通常没有明显的评估标准。尽管如此,我们还是可以想出一些方法(例如,使用用户反馈对模型进行排名),而且有很好的资源可以这样做。
第三个要考虑的改进是在带有嵌入的情节概要上使用深度学习方法:https://tfhub.dev/google/universal-sentence-encoder/2。这些方法应该允许我们将上下文结合到我们的推荐中,而不是像我们的模型目前使用的简单的单个单词。
最后,可以通过合并其他非文本特征(如体裁或数字特征)来改进模型。
几周后再来这里看看。我可能会写另一篇博文来实现这些改进。
请让我知道你对这个项目的看法,如果你有任何改进的建议。非常感谢所有建设性的意见。
参考
为了获得使用 Gensim MatrixSimilarity 类比较文档的灵感,我使用了奥瑞利的精彩教程“我如何使用 Python 比较文档相似度”:https://www . oreilly . com/learning/How-do-I-compare-document-similarity-using-Python
关于 Jaccard 和余弦相似度推荐器的使用,我非常感谢 Sanket Gupta 的教程“Python 中文本相似度度量概述”:https://towards data science . com/Overview-of-Text-Similarity-Metrics-3397 c 4601 f50
如何在 Azure 中创建自己的深度学习项目
使用 Azure 存储、带有 Keras 的数据块和 Azure ML 服务
1.介绍
深度学习对公司来说有很多实际应用,例如图像识别、视频索引和语音到文本转录。然而,对于公司来说,从深度学习项目开始可能会令人望而生畏。常见的问题是所用数据的敏感性和深度学习的复杂性,深度学习可以被视为机器学习的最高级。
2.目标
在本教程中,创建了一个样本深度学习项目,它能够使用 CIFAR-10 数据集(飞机、青蛙、船)识别图片类别。在这种情况下,执行以下步骤:
- Azure 存储用于安全地存储图片
- Azure Databricks 用于使用 Keras 和 TensorFlow 训练模型
- Azure ML 服务用于将模型版本化和部署为 HTTP 端点
这可以在下面的体系结构概述中描述:
2. High level overview
这个解决方案的关键是 Azure Databricks,这是一个针对 Azure 优化的基于 Apache Spark 的分析平台。它本机集成了其他 Azure 服务,如 Azure Active Directory 和 Azure Storage。在本博客的剩余部分,将执行以下步骤:
- 3.先决条件
- 4.创建深度学习项目
- 5.部署深度学习模型
- 6.结论
这是一个独立的教程,重点是在 Azure 中建立自己的深度学习项目,以“弄脏你的手”,从而更加熟悉这个主题。重点是深度学习的内部工作,最新的算法或计算机视觉 API。如果你对 AI 的 devops 更感兴趣,请参考我以前的博客,这里和关注安全,见这里。
3.先决条件
需要在同一资源组和同一位置创建以下资源。
4.创建深度学习项目
这一部分将执行以下步骤。
- 4a。将图片添加到存储帐户
- 4b。创建深度学习集群
- 4c。装载存储帐户
- 4d。单节点训练深度学习模型
- 4e。终止深度学习集群
4a。将图片添加到存储帐户
在本教程中, CIFAR-10 数据用于训练深度学习模型。在第一个模型中,将使用 2000 个图片的子集。随后,将创建第二个模型,该模型使用 60000 张图片的完整 CIFAR-10 数据集。
为了说明如何将 Azure Storage 与 Azure Databricks 结合使用,将在 Storage 帐户中存储 2000 张图片的子集。因此,请访问以下 URL,下载 2000 张图片的压缩文件。
[https://github.com/rebremer/devopsai_databricks/raw/master/sampledata/2000pics_cifar10.zip](https://github.com/rebremer/devopsai_databricks/raw/master/sampledata/2000pics_cifar10.zip)
随后,转到 Azure 门户并选择您的存储帐户。然后选择 blobs 并创建一个名为“2000picscifar10”的新容器。随后,将之前下载的 zip 文件上传到您的容器中。
4a1. Add zipfile to new container
最后,转到访问密钥,复制密钥或您的存储帐户。
4a3. Copy access keys
4b。创建深度学习集群
转到您的 Azure Databricks 工作区并转到群集。由于模型将在不使用 Spark 作业的情况下在驱动程序节点上训练,因此不需要创建(并支付)工人节点。因此,使用以下设置创建一个新的 GPU 集群:
4b1. Create GPU cluster without worker nodes
4c。装载存储帐户
转到您的 Azure Databricks 工作区,右键单击,然后选择导入。在单选按钮中,选择使用 URL 导入以下笔记本:
[https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/0_mountStorage.py](https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/0_mountStorage.py)
另请参见下图:
4c1. Import notebook to mount storage
打开您的节点簿并更改以下设置
storageaccount="<<your_storage_account>>"
account_key="<<your_key_in_step4a>>"
containername="2000picscifar10" # change if you used another name
请注意,在生产环境中,不得将密钥存储在笔记本中。相反,秘密范围将被使用,参见我的博客如何在数据科学项目中嵌入安全性。然后将笔记本连接到您创建的集群,然后单击 SHIFT+ENTER 来逐个单元地运行。
4c2. Attach notebook to cluster
在本笔记本中,将执行以下步骤:
- 将存储帐户装载到 Azure Databricks 工作区
- 解压缩存储帐户中的图片
- 列出并显示图片
4d。单节点训练深度学习模型
再次转到您的 Azure Databricks 工作区,右键单击,然后选择导入。在单选按钮中,选择使用 URL 导入以下笔记本:
[https://github.com/rebremer/devopsai_databricks/blob/master/project/modelling/1_DeepLearningCifar10NotebookExploration.py](https://github.com/rebremer/devopsai_databricks/blob/master/project/modelling/1_DeepLearningCifar10NotebookExploration.py)
在本笔记本中,将执行以下步骤:
- 从存储帐户导入和处理数据
- 根据存储帐户中的 2000 张图片建立模型
- 在完整 CIFAR-10 数据集的 60000 张图片的数据集上建立模型
- 将模型保存到磁盘(dbfs)
当您成功运行笔记本时,您可以看到预测的概述(红色是错误的预测)。
4d1. Overview of predictions
4e。终止深度学习集群
运行 GPU 集群的成本可能很高。由于我们在本教程的剩余部分不需要 GPU 集群,我们可以停止它。因此,转到您的集群并选择终止。
4e1. Terminate cluster
5.部署深度学习项目
这一部分将执行以下步骤。
- 5a。在数据块中创建新簇
- 5b。将库添加到集群
- 5c。注册模型和日志指标
- 5d。创建模型的 HTTP 端点
- 5e。测试模型的 HTTP 端点
5a。在数据块中创建新簇
在这一步中,将创建一个新的集群,用于部署我们的模型。既然模型已经训练好了,我们就不再需要 GPU 了。选择具有以下设置的群集
5a1. Non GPU cluster
5b。将库添加到集群
为了部署我们的模型,我们需要几个库。转到您的共享文件夹,右键单击共享并选择“创建库”。
4b1. Add Libraries
随后,选择 Pypi 并将以下库添加到共享文件夹中:
azureml-sdk[databricks]
keras
tensorflow
5c。注册模型和日志指标
在这一步中,模型及其指标将被添加到您的 Azure ML 服务工作区。在 Azure Databricks 工作区中导入以下笔记本。
[https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/2a_Cifar10KerasNotebookLogModel.py](https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/2a_Cifar10KerasNotebookLogModel.py)
打开您的节点簿并更改您的 Azure ML 服务工作区的以下设置(订阅 id 可在您的 Azure ML 服务工作区实例的概述选项卡中找到)。
workspace="<<your_name_of_azure_ml_service_workspace>>"
resource_grp="<<your_resource_group_amlservice>>"
subscription_id="<<your_subscriptionid_amlservice>>"
然后运行笔记本,再次使用 Shift+Enter 逐个单元格地浏览。在本笔记本中,将执行以下步骤:
- 在 2000 张图片上训练的模型的对数度量
- 在所有 60000 张图片上训练的模型的日志度量
- 在步骤 5d 中注册要部署的最佳模型
要查看指标,请转到门户,选择 Azure 机器学习工作区,然后选择 Expirement,见下文
5c1. Log metrics of model with 2000 pictures and all CIFAR-10 pictures
5d。创建模型的 HTTP 端点
将以下笔记本导入您的工作区
[https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/2b_Cifar10KerasNotebookDeployModel.py](https://raw.githubusercontent.com/rebremer/devopsai_databricks/master/project/modelling/2b_Cifar10KerasNotebookDeployModel.py)
再次更改参数,类似于步骤 5c。在这个笔记本中,为在所有图片上训练的模型创建一个端点。当你去门户网站,选择 Azure 容器实例,你会发现端点的 IP 地址。
5d1. Azure Container Instance with IP addresss
5e。测试模型的 HTTP 端点
要测试端点,需要完成以下步骤:
下图是一艘船的图片,转换为 base64 格式,用 Postman 发送,使用 endpoint 创建预测。
5e1. Picture of ship converted to base64 using https://onlinepngtools.com/convert-png-to-base64
5e2. Prediction of ship using HTTP endpoint
6.结论
在本教程中,创建了一个深度学习项目,其中使用了以下服务:
- Azure 存储帐户可以安全地存储图片
- Azure Databricks 与 Tensorflow 和 Keras 一起构建模型
- Azure ML 服务跟踪模型并创建 HTTP 端点
深度学习对企业有很多实际应用。然而,对于企业来说,从深度学习项目开始可能会令人望而生畏。创建您自己的示例项目并“亲自动手”是学习和熟悉该主题的好方法。
6. Sample project overview
最后,非常感谢我的同事 Ilona Stuhler,她非常友好地向我提供了这个课题的重要内幕,并把她的项目捐赠给了我。
如何创建自己的深度学习平台:完整的硬件指南。
以及从长远来看,它如何比云解决方案更快、更便宜。
这篇博客是关于建立一个 GPU 工作站,像 Lambda 的预建 GPU 深度学习平台一样,并作为一个指南,指导你应该看什么是绝对的东西,以确保你准备创建自己的深度学习机器,而不是意外地购买昂贵的硬件,后来证明不兼容并造成问题。但是在我们开始之前…
你真的需要吗?
当我开始更认真地对待深度学习或机器学习时,我遇到的一件事是:计算
我过去做过机器人,觉得现在是我自己创建终极深度学习平台的最佳时机,它将像任何东西一样处理信息,并以极快的速度工作。
但是很明显,当你有云计算时,为什么要花这么多钱。当你不需要维护任何机器,也不担心它有一天会过时时,为什么不按照你的意愿,在你想要的任何时候建立另一个实例呢?
好吧,深度学习的故事说的是别的东西。博客[1][2][3]比较了它的多个方面,漂亮地概括了一切。最后:
所以,我们来创造自己的深度学习机器吧。
但是,首先,如果你不是一个 DIY 的人,并且正在寻找一个预建的深度学习系统,我推荐 Exxact 的深度学习工作站,由英伟达 RTX 2080 Ti、特斯拉 V100、泰坦 RTX 或 RTX 8000 GPU 提供支持,并提供 3 年保修。他们的工作站起价 3700 美元。
目录:
我们将在接下来的章节中详细讨论每一项。
中央处理器
Ryzen threadripper CPU
鉴于现在大部分深度学习模型都运行在 GPU 上,CPU 的使用主要是为了数据预处理。
如果您经常处理千兆字节的数据,并且如果您在分析部分做了大量工作,必须进行大量查询才能获得必要的见解,我建议您投资一个好的 CPU。
否则,投资一个中级处理器不会有任何坏处,因为 CPU 只在 GPU 进行训练时帮助批处理调度和其他小进程。
AMD 的 threadripper 系列非常强大,性价比极高。我选择了 Threadripper 1900x,8 核 16 线程 CPU。
重要事项:
由于高性能价格比,我随时会选择 AMD。这就像是为相同的性能支付了英特尔同类产品一半的价格。
搜索 youtube 进行安装或查看主板指南。这非常简单明了,但是芯片有点脆弱。小心轻放。
储存;储备
三个可用选项是:
- HDD (硬盘驱动器)
- SSD (固态硬盘)
- NVME SSD (非易失性存储器快速)
硬盘是一个旋转的磁盘,上面有毛笔写和读比特。由于它是机械的和完全机动化的,所以性能很慢,占用更多的空间,并且更容易损坏和破坏数据。
固态硬盘:它们体积小,速度快,没有任何移动部件。虽然有点贵。这在整体体验中当然很重要。当操作系统加载到固态硬盘存储之上时,会变得非常流畅。在深度学习中,当你几乎每次都要处理数 GB 的数据时,文件传输速度非常快。SATA 3 插槽使用 AHCI 驱动程序,最高传输速度可达 600 Mbps。
**NVMe 固态硬盘:**不使用 SATA 总线,而是使用 PCIe,性能大幅提升。此外,使用的传输协议不是 AHCI,而是 NVMe,提供了高效的并行处理。最后,我们这里说的是 2–3gb/s。不同型号的数字不同。
它仍然是一项新技术,就其提供的功能而言,它比 SSD 贵得多。与常规固态硬盘相比,NVME 固态硬盘在操作系统中的性能几乎不会有所提升,而且文件传输的等待时间也会大大减少。此外,NVMe 的意思是,确保主板有 m2 插槽,这也增加了它的价格,因为旧的没有它。
要了解更多关于 SSD 和 NVME SSD 技术的信息,你可以去看看 Kingston[ 20 ]写的一篇短小精悍的博客,里面有很多对比两者的视觉图像。此外,这个 youtube 视频用动画很好地解释了 NVMe。
英特尔推出了具有 3D 交叉点晶体管的 Optane 存储,可提供更高的密度和性能。但是非常昂贵,根本不值这个价钱。更多关于 Optane 的信息在这里[ 6 ]。
我选择了 500 GB 的 NVMe M2 固态硬盘,因为我可以为我获得的高速度支付额外的费用。不然 SSD 比 HDD 好很多。
重要事项:
假设您的数据将驻留在 RAM 或 GPU VRAM 中。在训练数据时,存储并不重要。
从性价比来看,投资固态硬盘比投资硬盘更好。
NVMe SSD 以为很快就贵了,还需要兼容主板。
母板
正如你所看到的,它们有不同的尺寸。标准尺寸决定了你想要的箱子类型。根据您的需要,在给定的主板上,您可以检查:
- 内存的 DIMM 插槽
- GPU 的 PCIe 插槽
- NVMe 固态硬盘的 M2 插槽(如果你很快就会使用)
- 固态硬盘的 SATA 端口
- 根据需要提供雷电 3/USB 3.0/2.0 接口。
为将来的升级提供额外的插槽是件好事。人们一般会升级到更高的 RAM,并且将来还会添加多个 GPU。
选择会因人而异。预装机器通常通过使用没有足够插槽用于未来升级的主板来节省资金。你可以在这里选择。
重要事项:
确保你的 CPU 支持给定的主板。可以选择 CPU 和主板的最佳组合来省钱。
许多人关心每个 PCIE 插槽的通道数量。用几个 GPU 完全没关系。在 Tim dettmers 的博客[ 7 ]中,“CPU 和 PCI-Express”一节以 Imagenet 数据集为例对此进行了精彩的解释。因此,不要因为另一家提供 16 车道 PCIe 而不是 8 车道就额外付费。
如果您计划在未来添加更多 GPU,请确保 PCIE 插槽足够远。鉴于这些天来 GPU 如何在他们的 beafy 散热器中采用多风扇结构,随着 NVIDIA 不断增加越来越多的核心,大多数 GPU 占用 2 个 PCIE 插槽的空间。(否则,你将不得不寻找一个垂直安装的 GPU 连接器,这是昂贵的,也不容易在大多数国家获得。)
GPUs taking space of 2 PCIe slots.
冷却
是的,考虑到硬件正在经历的压缩级别,这个主题需要自己的部分。
你必须保持冷静的两个元素是 CPU 和 GPU。
风扇有不同的尺寸。
此外,240/360 毫米风扇配置仅指并排安装 2/3 个 120 毫米风扇。
CPU 冷却
a typical CPUs exposed top-view
Two types of CPU cooler
- 风扇冷却器
- 一体式液体冷却
正如你所看到的,液体冷却和风扇一起有一个泵,使水在管子周围循环。有些主板带有单独的 CPU 风扇和泵连接器。它们也可以用于常规风扇端口。在传统的风扇中,这些热量是通过铜管传递给风扇的。这意味着只有一个连接器用于风扇。
两者都有相似的表现,但各有不同。我强烈推荐观看关于这个的 LinusTechTips youtube 视频。
GPU 冷却
1st one is open-air. 2nd is a blower-style config.
GPU 散热是内置的,开箱即用。这两种配置是:
- 露天冷却器
- 鼓风机式风扇
Airflow in both the configurations.
因为露天扔在所有方向的空气,并有多达 3 个风扇,他们更适合单 GPU PC,也给更好的超频结果。
这在多 GPU 系统中成为一个问题。一个 GPU 抛出的空气被其他 GPU 消耗,增加了它们的温度,这种情况一直循环下去,直到整个系统上升到非常高的温度。因此,在多 GPU 配置中,吹风机式更好,因为它可以带走电脑机箱中的热量,新鲜空气可以进入 GPU。
liquid cooling hardware on a GPU
液冷是存在的,但这需要打开 GPU 并将其安装到单独的硬件上,这很可怕,也使保修无效,即使有一天你想达到这一水平,也很难在所有国家获得零件。
多 GPU 值得额外付出代价吗?
虽然单个 GPU 可以处理,但大多数情况下温度不会超过 80 度。但是对于多 GPU 系统,冷却成为一个大问题。即使 SLI 桥或 NVLink(现在由 NVIDIA 公司命名)可以将多个 GPU 连接在一起,优化也会受到严重影响。理想情况下,将 2 个 GPU 连接在一起应该可以提供 2 倍的性能,但在大多数情况下,与使用单个 GPU 相比,您最终只能获得 40%的额外提升。这不仅消耗更多的电力,导致更高的电费,而且供暖问题使事情变得更糟。所以,如果你准备好付额外的钱,并且非常需要它,我建议你去试试。
一体式液体冷却:
非常昂贵的一体式液冷存在。部件在大多数国家都不容易买到,而且如果你不确定要放入的电脑外壳的兼容性,购买和安装也有风险。此外,它们可能会在某些时候泄漏,更换可能是一个大问题。总的来说,额外的努力也不值得的性能或价格。
要有多少粉丝?
良好的空气流动是深度学习装备的必备条件。这可以通过进气和排气风扇来实现。但是,极限是什么?
我建议您在前面安装两个进气风扇,在后面安装一个排气风扇。它会给你足够的气流。
在这之后,增加更多的风扇只会使温度稍微下降。LinusTechTips 视频[ 9 ]通过在许多不同的风扇和位置配置中做实验,为我解决了这一切。
重要事项:
确保检查您订购的 CPU 冷却解决方案是否适合主板上的特定支架。例如 AMD Threadripper CPU 使用 TR4 安装支架。
确保使用热敷膏。很奇怪,一个人如何能够通过在笔记本电脑上再次应用热贴来获得显著的提升。Dave2D 的 youtube 视频[10]视频详细展示了统计数据。
确保你把风扇放在正确的位置。安装并打开主板后,务必检查所有风扇的气流方向。
检查主板支持的风扇数量。否则,您可能需要将它们直接连接到 PSU,让它们一直全速运行,而不是通过主板软件来控制它们的速度。
情况
好吧,这可能是个问题。无论你如何小心,有时,电缆可能会稍微短一点,或者 RAM 会妨碍你计划放在机箱顶部的 CPU 散热器。小问题就来了。有些也会让你不好过。一些 PSU 或主板制造商也提供电缆扩展器。如果你想获得一个流畅的构建体验,你也可以观看在线 youtube 构建视频并获得相同的产品。但是在大多数情况下,事情都解决得很好。
但是另一个能提供最好的气流!
在大多数情况下,适当的气流不是问题。这只是一种营销策略,不同的外壳制造商宣传他们如何为组件提供最佳气流。
重要事项:
在极少数情况下,电缆长度可能是个问题。你可以得到扩展器。
有些箱子有可拆卸的风扇。有些给它们预装在其中,有些有可拆卸的风扇。
确保根据您的主板尺寸选择合适的型号。一个给定尺寸的箱子也可以装更小的型号。例如,电子 ATX 案件将支持其较小的版本,如迷你 ATX 或微型 ATX。相应地钻孔。因此,错误地得到一个更大的案件不是问题。尽管如此,有些人还是喜欢看办公桌上的小巧美人。
确保你有一个适合 PSU 的房间。他们有一个单独的 PSU 车厢。如果可能的话,检查一下它的大小。
音频插孔、USB type 2/3、thunderbolt 的前置 IO 均视情况而定。所以一定要根据自己的需求来选择。显然,您可以使用主板上的端口,但它们将位于电脑的背面。
有些机箱仅在顶部安装液体 CPU 冷却器,而有些机箱仅允许将风扇放在前面。确保检查可能的配置。
before and after cable management
有足够的拉链和扎带,便于完美的线缆管理。请记住,线缆管理是一门艺术。
您可以使用 PCpartPicker 的网站[11]查看您选择的所有零件之间的兼容性。
随机存取存储
everything can come with LEDs in them
如果您处理大型数据集,如图像或某种日志数据,您的数据可以完全放在 RAM 中,这有助于显著加快处理时间,因为这是 CPU 在没有将数据放入 L1 或 L2 缓存后使用的内存。对于通常不适合 VRAM 的数据集,在 RAM 和 GPU VRAM 之间进行传输。与任何其他存储解决方案相比,这是非常快的,传输速率约为 20 Gbps。
机器中应该有大量的 RAM,但是如果您有大量的预处理工作要做,那么 8 到 16 GB 就足够了。
与 XMP 或极端的内存配置文件设置,可以超频内存到更高的速度。但实际上,这并不重要。时钟速度为 3000 MHz 的 RAM 比 2400 MHz 的工作速度稍快,但这并不是一个很明显的改进,因此性能价格比非常低。此外,你的 RAM 速度一般不会成为系统的瓶颈,因此 17 Gbps 的传输速度会使 PC 比 20 Gbps 的慢。
重要事项:
确保您使用的 DDR4 RAM 与您的主板兼容。大多数主板制造商也会提供支持的硬件列表。
安装多个 RAM 记忆棒时,不要混用不同的时钟速度和制造商。建议使用完全相同类型的 RAM。
内存插槽号已给定,根据您拥有的内存数量,您必须将其放入各自的插槽中。请参阅主板手册。
这些老虎机让我想起了当年我们用来购买和玩的游戏盒!!。
(left) a full gaming console. (right) Inside of a gaming cassette
确保你在内存巷回去的时候,眼泪没有掉在主板上。即使在它的顶部做了最后的覆盖电镀,插槽也有线路开放,人类的眼泪含有 0.3 毫克的盐,足以打碎东西。顺便说一下,海水中每一滴含有 1.75 毫克的盐。
程序存储单元(Program Storage Unit)
获得 PSU 时需要注意两件事:
- PSU 电力公司
- PSU 港口
对于第一个问题,您需要找出系统的总功耗。对于功耗较小的机器,输出功率较高是可以的,但反之则不行。使用以下公式计算总功耗(瓦特):
n —您希望拥有的 GPU 总数,也包括未来增加的数量。
m——您拥有的硬盘或固态硬盘的总数,也包括未来增加的硬盘或固态硬盘。
额外的 200 瓦用于其他外围设备,并留有安全余量。
你可以很容易地在他们的官方网站上找到每个组件的功率使用情况。
对于第二个,确保提供的插槽数量与您要安装的数量相等。或者简单地添加 PCPartPicker 的网站列表[ 12 ]中的所有部件,您将在最终兼容性部分了解您是否缺少总端口。
PSU 主要有:
- CPU 插槽:显然是为了 CPU
- 外设插槽——GPU 和其他东西。
- SATA 插槽:用于存储解决方案
- 24 针 ATX 插槽:为您的主板供电
一个好的电源设备是必须的。气流,即使风扇数量较少,也会自行解决,但请确保为您的系统提供清洁和充足的电力。
重要事项:
切勿将转换器插头用于 PSU 插座。适配器与插头轻微接触,会产生大量热量。此外,适配器的材料大多很便宜,并有指定的安培容量,如果超过将烧毁插座。
由于印度的电源插座有 5 安培和 15 安培的支持,对于深度学习钻机,你必须将其放在 15 安培容量的更大插座中。如果你的 PSU 上有 G 型英国插头,最好切断插头并接上你需要的支持更高安培输出的插头,而不是放一个适配器。
由于 15 安培的插头离我的钻机很远,我面临着扩展问题。最后,我去了一个 9 米的额外电缆扩展。我确保延长电线的质量是一流的,因为距离越长,电阻越大,最终电压降越大。仅使用所需厚度的高质量铜线。
显示器和无线键盘
由于我们不做游戏装备,4K 显示器或 144 赫兹刷新率显示器不是我们要找的。
Tim Dettmers 在他的博客中提到,他是如何使用 3 台显示器的,并且非常喜欢。我非常同意他的观点,但是对我来说,我想两台显示器已经足够了。但是,多显示器设置肯定会让你更有效率。
鉴于如今显示器已经变得如此便宜,你可以很容易地选择 LED,而不是 24 或 27 英寸屏幕的 LCD。
键盘和鼠标也是如此。带有 RGB 照明和长按键行程的机械开关的游戏设备是不必要的。
我个人更喜欢笔记本电脑风格的小键盘。此外,无线电话比有线电话稍微贵一点,但是它让环境看起来更干净、更漂亮。如今,无线键盘和鼠标的单个 USB 端口也出现了。
重要事项:
查看 GPU 规格,了解其支持的显示器数量。几乎都支持一个以上。
您可能需要购买一个显示器端口来连接 hdmi/VGA 转换器,以支持多个显示器。检查规格,看看你的 GPU 有多少 HDMI,VGA 或显示端口。
国家政治保卫局。参见 OGPU
这是你深度学习装备的核心。真正训练的地方。这当然是一个大话题,需要一个独立的博客。但是,至少要拿出点东西来,我建议去:
- RTX 2080 Ti 或
- RTX 2070(这个不支持 NV link)——便宜很多。
他们有一个 16 位精度选项可以加速。新架构有一些非常好的性能增益。
你也可以通过购买易贝的二手图形处理器来节省一大笔钱。
一辆 GTX 1080 Ti 也是一个很好的选择。此外,不要认为使用旧的会降低性能,这在另一个 LinusTechTips 视频中再次得到了证明。
重要事项:
我强烈推荐查看蒂姆·德特默的成熟博客[ 14 ],他在那里对这个话题做了绝对公正的评价。
我强烈建议只使用 NVIDIA GPUs 进行深度学习,因为 CUDNN 和 CUDA 工具包与目前的深度学习库高度兼容,无论是 Keras、Tensorflow、PyTorch 还是任何其他库。
安装操作系统
深度学习软件首先与基于 Linux 的机器兼容。
我已经安装了 Ubuntu 18.04,因为它现在有 LTS(长期支持),我没有检查在我以前的 16.04 LTS 版本上工作的不兼容的库。但是主要的深度学习库根本不会有任何问题。
拿一台可以工作的笔记本电脑。从 Ubuntu 的官网[ 15 ]下载操作系统,如果可能的话别忘了捐款支持。使用像 Rufus[ 16 ]这样的免费软件创建一个可启动的笔式驱动器,将其插入端口并启动您的电脑。
你会看到 BIOS。一般是删除按钮或者某个 Fn 按钮。检查所有连接的组件,看看是否一切都被检测到。
您可能需要优先选择连接的 USB 进行引导,以确保可引导磁盘得到加载。
按照说明安装 Ubuntu。
在这段 youtube 视频中可以看到这整个过程[ 17 ]。
最后的想法
最后,这是一个有趣和令人兴奋的过程,你一定会喜欢的。如果你过去没有造过机器,那也没关系。没什么复杂的。硬件社区为您提供了全面的保护。现在事情非常模块化。还有一些网站可以让你看到所有部件的兼容性,比如 PC Part Picker[ 18 ]。你可以随时在 Bitwit[ 19 ]等频道参考 youtube 上充满硬件构建视频的视频,看看如何做到这一点,顺便说一句,当涉及到生活时,观看它是纯粹的幸福。
感谢你的阅读,祝贺你坚持到最后,感谢桑德普·T·T21 编辑了这篇博客。下次见,爱 u 3000:)
参考
[1]medium.com,陈明杰,为什么建造自己的深度学习计算机比 AWS (2018)便宜 10 倍
[2]詹妮弗·维拉,选择你的深度学习基础设施:云与内部辩论 (2018),determined.ai
[3] 预构建 vs 构建自己的深度学习机器 vs GPU 云(AWS) (2018),bizon-tech.com
[4] 云与内部部署:深度学习哪个更好?(2018) ,exxactcorp.com
[5] Powercert 动画视频,Youtube.com m . 2 NVMe 固态硬盘讲解— M.2 vs 固态硬盘 (2018)
[6] 英特尔 Optane 技术,Intel
[7]蒂姆·德特默斯,深度学习的完整硬件指南 (2018),TimDettmers.com
[8] Linus Tech Tips,为什么你不应该用水冷却你的电脑 (2019),Youtube.com
[9] Linus Tech Tips, Case 粉丝——你应该有多少? (2015),Youtube.com
[10]戴夫·李, $12 Hack 提升你的笔记本电脑性能! (2017),Youtube.com
[12] 系统建造者,pcPartPicker.com
[13] Linus Tech Tips,性能下降—这是真的吗? (2016),Youtube.com
[14] Tim Dettmers,深度学习需要哪些 GPU:我在深度学习中使用 GPU 的经验和建议 (2019),TimDettmers.com
Ubuntu.com Ubuntu 桌面下载 18 . 04 . 2
[16] Rufus ,Rufus.ie
[17] LinuxPlus,如何安装 Ubuntu 18.04 Youtube.com LTS(2018)
[18] 建造指南,pcPartPicker.com
【19】bit wit,如何搭建 PC!步步为营 (2017),Youtube.com