【邁向圖神經網絡GNN】Part5: 建構 GNN model 實作 Cora 資料集結點分類任務

閱讀時間約 34 分鐘

上一篇我們通過 pytorch 實作自定義的 message passing class,這篇要實作整個 GNN model ,以及使用 cora dataset 進行分類任務,並比較各個模型的成效,如果還沒看過上一篇的人可以點以下連結:

【邁向圖神經網絡GNN】Part1: 圖數據的基本元素與應用

【邁向圖神經網絡GNN】Part2: 使用PyTorch構建圖形結構的概念與實作

【邁向圖神經網絡GNN】Part3: 圖神經網絡的核心-訊息傳遞機制

【邁向圖神經網絡GNN】Part4: 實作圖神經網路訊息傳遞機制

Photo by Markus Spiske on Unsplash

Photo by Markus Spiske on Unsplash

從 torch 下載 Cora 資料集

from torch_geometric.datasets import Planetoid
from torch_geometric.transforms import NormalizeFeatures
dataset = Planetoid(root='data/Planetoid', name='Cora', transform=NormalizeFeatures())

Cora 資料集是一個常用於圖神經網絡 (Graph Neural Networks, GNN) 研究的標準數據集。它主要包含機器學習領域的科學論文,這些論文被分類成七個類別,如神經網絡、機器學習、人工智能等。Cora 數據集的主要特點和組成如下:

  1. 節點:每個節點代表一篇科學論文。
  2. :如果一篇論文引用了另一篇論文,則這兩篇論文之間存在一條邊。這種表示方式將論文集結成一個引用網絡。
  3. 特徵:每個節點(論文)都有一個對應的特徵向量,這個特徵向量是基於論文的單詞使用情況的稀疏二進制向量。特徵向量的每一維表示一個單詞是否在該論文中出現。
  4. 類別:每篇論文都被標註為七個領域中的一種,例如:人工智能、神經網絡、機器學習… 等。

5. 使用這個資料集可以進行分類任務檢測: 輸入節點與關係和其特徵,預測分類該論文為哪一類別。

Cora 資料集簡單資料觀察

print()
print(f'Dataset: {dataset}:')
print('======================')
print(f'Number of graphs: {len(dataset)}')
print(f'Number of features: {dataset.num_features}')
print(f'Number of classes: {dataset.num_classes}')

graph = dataset[0] # Get the first graph object.

print()
print(graph)
print('===========================================================================================================')

# Gather some statistics about the graph.
print(f'Number of nodes: {graph.num_nodes}')
print(f'Number of edges: {graph.num_edges}')
print(f'Average node degree: {graph.num_edges / graph.num_nodes:.2f}')
print(f'Number of training nodes: {graph.train_mask.sum()}')
print(f'Training node label rate: {int(graph.train_mask.sum()) / graph.num_nodes:.2f}')
print(f'Has isolated nodes: {graph.has_isolated_nodes()}')
print(f'Has self-loops: {graph.has_self_loops()}')
print(f'Is undirected: {graph.is_undirected()}')

輸出:

Dataset: Cora():
======================
Number of graphs: 1
Number of features: 1433
Number of classes: 7

Data(x=[2708, 1433], edge_index=[2, 10556], y=[2708], train_mask=[2708], val_mask=[2708], test_mask=[2708])
===========================================================================================================
Number of nodes: 2708
Number of edges: 10556
Average node degree: 3.90
Number of training nodes: 140
Training node label rate: 0.05
Has isolated nodes: False
Has self-loops: False
Is undirected: True
  1. 圖的數量:數據集中只有一個圖。在這種情況下,整個數據集是一個大的圖,其中節點表示科學論文,邊表示論文間的引用關係。
  2. 特徵數量:每個節點(論文)都有1433個特徵。這些特徵是基於文本內容的二進制向量,代表了1433個不同的單詞是否出現在該論文中。
  3. 類別數量:有7個不同的類別,每個類別代表論文所屬的科學領域。
  4. 節點和邊的數量
  • 節點數量:2708,表示有2708篇科學論文。
  • 邊的數量:10556,表示這些論文間共有10556次引用。

5. 平均節點度數:約3.90,這表明每篇論文平均被其他論文引用了3.90次。

6. 訓練節點

  • 訓練節點數量:140,這表示只有140篇論文的類別標籤會用於訓練模型。
  • 訓練節點標籤比率:約0.05,即大約5%的論文用於訓練,這是一個相對較少的比例,表明大部分數據用於驗證和測試。

7. 其他圖特性

  • 是否有孤立節點:False,表示所有節點至少與一個其他節點有連接。
  • 是否有自循環:False,表示沒有任何節點指向自己的邊。
  • 是否為無向圖:True,這表示引用關係被視為雙向的,即如果節點A引用節點B,那麼從節點B到節點A也被認為存在一個邊。

實作 GNN model

class myGNN(torch.nn.Module):
def __init__(self, layer_num, input_dim, hidden_dim, output_dim, aggr='mean', **kwargs):
super(myGNN, self).__init__()
self.layer_num = layer_num

self.encoder = nn.Linear(input_dim, hidden_dim)

# you can use the message passing layer you like, such as GCN, GAT, ......
self.mp_layer = NN_MessagePassingLayer(input_dim=hidden_dim, hidden_dim=hidden_dim,
output_dim=hidden_dim, aggr=aggr)

self.decoder = nn.Linear(hidden_dim, output_dim)

def forward(self, x, edge_index):
x = self.encoder(x)
for i in range(self.layer_num):
x = self.mp_layer(x, edge_index)
node_out = self.decoder(x)
return node_out

GNN model 可以將 nn 類的結構分為三個主要部分,每個部分都扮演著圖神經網絡中的關鍵角色。以下是每個部分的具體說明及其功能:

1. Encoder: Encoder 的主要作用是將輸入數據的維度從較小的輸入維度(例如,原始特徵維度)擴展到更高的隱藏維度。這種維度的提升有助於在後續的神經網絡層中捕捉更複雜的特徵,從而提高學習能力和表達能力。

2. Message Passing Layer: Message passing layer 是圖神經網絡的核心,負責節點之間信息的傳遞和整合。您可以在這一層中使用各種不同的 message passing 演算法,如 GCN (Graph Convolutional Network), GAT (Graph Attention Network) 等。這個階段的目的是利用節點之間的連接關係來更新節點的特徵表示。

3. Decoder:目的是將通過 message passing 得到的特徵表示維度降低,使其與目標輸出維度一致。這是為了確保最終輸出的維度符合特定的任務需求,如節點分類中每個類別的預測概率。

---

接下來就是各種模型實驗與比較

GNN model

使用上述定義的 GNN model,訓練起來成效不太好, Test acc=0.30 而已,而且 train 的過程中 loss 降不太下來,大多維持在 0.7 

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torch_geometric.nn as geom_nn
from IPython.display import Javascript # Restrict height of output cell.

# 定義 myGNN 模型
class myGNN(torch.nn.Module):
def __init__(self, layer_num, input_dim, hidden_dim, output_dim, aggr='mean'):
super(myGNN, self).__init__()
self.layer_num = layer_num
self.encoder = nn.Linear(input_dim, hidden_dim)
self.mp_layer = geom_nn.GCNConv(hidden_dim, hidden_dim, aggr=aggr)
self.decoder = nn.Linear(hidden_dim, output_dim)

def forward(self, x, edge_index):
x = self.encoder(x)
for i in range(self.layer_num):
x = self.mp_layer(x, edge_index)
x = F.relu(x) # Optional: Apply a non-linear activation
x = self.decoder(x)
return x

# 初始化模型和優化器
model = myGNN(layer_num=2, input_dim=dataset.num_features, hidden_dim=16, output_dim=dataset.num_classes)
optimizer = optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)
criterion = nn.CrossEntropyLoss()

# 定義訓練函數
def train():
model.train()
optimizer.zero_grad() # Clear gradients.
out = model(graph.x, graph.edge_index) # Perform a single forward pass.
loss = criterion(out[graph.train_mask], graph.y[graph.train_mask]) # Compute the loss solely based on the training nodes.
loss.backward() # Derive gradients.
optimizer.step() # Update parameters based on gradients.
return loss

# 定義測試函數
def test():
model.eval()
out = model(graph.x, graph.edge_index)
pred = out.argmax(dim=1) # Use the class with highest probability.
test_correct = pred[graph.test_mask] == graph.y[graph.test_mask] # Check against ground-truth labels.
test_acc = int(test_correct.sum()) / int(graph.test_mask.sum()) # Derive ratio of correct predictions.
return test_acc

# 訓練和測試循環
for epoch in range(1, 101):
loss = train()
print(f'Epoch: {epoch:03d}, Loss: {loss:.4f}')

test_acc = test()
print(f'Test Accuracy: {test_acc:.4f}')

# 可視化輸出
model.eval()
out = model(graph.x, graph.edge_index)
visualize(out, color=graph.y)
display(Javascript('''google.colab.output.setIframeHeight(0, true, {maxHeight: 300})'''))

輸出結果

Epoch: 001, Loss: 1.9620
Epoch: 002, Loss: 1.9599
Epoch: 003, Loss: 1.9578
Epoch: 004, Loss: 1.9557
Epoch: 005, Loss: 1.9536
Epoch: 006, Loss: 1.9517
Epoch: 007, Loss: 1.9499
Epoch: 008, Loss: 1.9484
Epoch: 009, Loss: 1.9472
Epoch: 010, Loss: 1.9463
Epoch: 070, Loss: 1.1654
Epoch: 071, Loss: 1.1427
Epoch: 072, Loss: 1.1213
Epoch: 073, Loss: 1.0998
Epoch: 074, Loss: 1.0781
Epoch: 075, Loss: 1.0575
Epoch: 076, Loss: 1.0385
Epoch: 077, Loss: 1.0197
Epoch: 078, Loss: 1.0012
Epoch: 079, Loss: 0.9838
Epoch: 080, Loss: 0.9677
Epoch: 081, Loss: 0.9528
Epoch: 082, Loss: 0.9386
Epoch: 083, Loss: 0.9234
Epoch: 084, Loss: 0.9078
Epoch: 085, Loss: 0.8938
Epoch: 086, Loss: 0.8806
Epoch: 087, Loss: 0.8677
Epoch: 088, Loss: 0.8559
Epoch: 089, Loss: 0.8421
Epoch: 090, Loss: 0.8272
Epoch: 091, Loss: 0.8136
Epoch: 092, Loss: 0.8029
Epoch: 093, Loss: 0.7931
Epoch: 094, Loss: 0.7788
Epoch: 095, Loss: 0.7640
Epoch: 096, Loss: 0.7530
Epoch: 097, Loss: 0.7432
Epoch: 098, Loss: 0.7308
Epoch: 099, Loss: 0.7168
Epoch: 100, Loss: 0.7069
Test Accuracy: 0.3050
raw-image

果然從視覺化來看,分類任務成效並不好,稍微再調整一下!

class myGNN(torch.nn.Module):
def __init__(self, layer_num, input_dim, hidden_dim, output_dim, aggr='mean'):
super(myGNN, self).__init__()
self.layer_num = layer_num
self.encoder = nn.Linear(input_dim, hidden_dim)
self.bn_layers = nn.ModuleList([nn.BatchNorm1d(hidden_dim) for _ in range(layer_num)])
self.mp_layers = nn.ModuleList([geom_nn.GCNConv(hidden_dim, hidden_dim, aggr=aggr) for _ in range(layer_num)])
self.decoder = nn.Linear(hidden_dim, output_dim)

def forward(self, x, edge_index):
x = self.encoder(x)
for i in range(self.layer_num):
x = self.mp_layers[i](x, edge_index)
x = F.relu(x)
x = self.bn_layers[i](x)
x = self.decoder(x)
return x
  • 增加 Batch Normalization : 讓訊息傳遞層因為有 noremalize ,傳遞更穩定,模型也盡快收斂
  • 獨立的訊息傳遞層與 modulize : 原本的方法是,單一的訊息傳遞層多次重複使用,調整後每個會是獨立的,允許每層學習到不同的權重與特徵。

調整後輸出:

Epoch: 001, Loss: 2.0951
Epoch: 002, Loss: 1.8160
Epoch: 003, Loss: 1.5728
Epoch: 004, Loss: 1.4217
Epoch: 005, Loss: 1.2931
Epoch: 006, Loss: 1.1803
Epoch: 007, Loss: 1.0787
Epoch: 008, Loss: 0.9838
Epoch: 009, Loss: 0.9088
Epoch: 010, Loss: 0.8384
Epoch: 070, Loss: 0.0025
Epoch: 071, Loss: 0.0024
Epoch: 072, Loss: 0.0024
Epoch: 073, Loss: 0.0023
Epoch: 074, Loss: 0.0023
Epoch: 075, Loss: 0.0022
Epoch: 076, Loss: 0.0022
Epoch: 077, Loss: 0.0021
Epoch: 078, Loss: 0.0021
Epoch: 079, Loss: 0.0021
Epoch: 080, Loss: 0.0020
Epoch: 081, Loss: 0.0020
Epoch: 082, Loss: 0.0019
Epoch: 083, Loss: 0.0019
Epoch: 084, Loss: 0.0019
Epoch: 085, Loss: 0.0019
Epoch: 086, Loss: 0.0018
Epoch: 087, Loss: 0.0018
Epoch: 088, Loss: 0.0018
Epoch: 089, Loss: 0.0018
Epoch: 090, Loss: 0.0017
Epoch: 091, Loss: 0.0017
Epoch: 092, Loss: 0.0017
Epoch: 093, Loss: 0.0017
Epoch: 094, Loss: 0.0017
Epoch: 095, Loss: 0.0017
Epoch: 096, Loss: 0.0016
Epoch: 097, Loss: 0.0016
Epoch: 098, Loss: 0.0016
Epoch: 099, Loss: 0.0016
Epoch: 100, Loss: 0.0016
Test Accuracy: 0.3560

訓練過程中 loss 有下降,但在 test case 表現不佳,僅 0.3560 ,是 overfitting 的現象,那我們再增加 dropout 去調整。

class myGNN(torch.nn.Module):
def __init__(self, layer_num, input_dim, hidden_dim, output_dim, dropout_rate=0.55, aggr='mean'):
super(myGNN, self).__init__()
self.layer_num = layer_num
self.encoder = nn.Linear(input_dim, hidden_dim)
self.bn_layers = nn.ModuleList([nn.BatchNorm1d(hidden_dim) for _ in range(layer_num)])
self.mp_layers = nn.ModuleList([geom_nn.GCNConv(hidden_dim, hidden_dim, aggr=aggr) for _ in range(layer_num)])
self.dropout = dropout_rate
self.decoder = nn.Linear(hidden_dim, output_dim)

def forward(self, x, edge_index):
x = self.encoder(x)
for i in range(self.layer_num):
x = F.relu(x)
x = F.dropout(x, p=self.dropout, training=self.training)
x = self.bn_layers[i](x)
x = self.mp_layers[i](x, edge_index)
x = self.decoder(x)
return x

輸出

Epoch: 001, Loss: 1.9891
Epoch: 002, Loss: 1.9465
Epoch: 003, Loss: 1.9275
Epoch: 004, Loss: 1.9061
Epoch: 005, Loss: 1.8830
Epoch: 006, Loss: 1.8660
Epoch: 007, Loss: 1.8757
Epoch: 008, Loss: 1.8021
Epoch: 009, Loss: 1.8021
Epoch: 010, Loss: 1.7374
Epoch: 070, Loss: 0.3411
Epoch: 071, Loss: 0.3400
Epoch: 072, Loss: 0.3191
Epoch: 073, Loss: 0.4393
Epoch: 074, Loss: 0.2978
Epoch: 075, Loss: 0.3700
Epoch: 076, Loss: 0.3445
Epoch: 077, Loss: 0.3263
Epoch: 078, Loss: 0.4001
Epoch: 079, Loss: 0.3582
Epoch: 080, Loss: 0.3403
Epoch: 081, Loss: 0.3091
Epoch: 082, Loss: 0.3415
Epoch: 083, Loss: 0.3156
Epoch: 084, Loss: 0.2650
Epoch: 085, Loss: 0.3692
Epoch: 086, Loss: 0.2819
Epoch: 087, Loss: 0.2802
Epoch: 088, Loss: 0.2628
Epoch: 089, Loss: 0.1985
Epoch: 090, Loss: 0.2510
Epoch: 091, Loss: 0.2499
Epoch: 092, Loss: 0.3362
Epoch: 093, Loss: 0.2442
Epoch: 094, Loss: 0.3921
Epoch: 095, Loss: 0.2608
Epoch: 096, Loss: 0.3405
Epoch: 097, Loss: 0.2851
Epoch: 098, Loss: 0.2690
Epoch: 099, Loss: 0.2424
Epoch: 100, Loss: 0.2656
Test Accuracy: 0.6230

Test acc 有明顯的提升到 0.623 

raw-image

這時候可視化輸出結果,看起來有比原本分得更好,那我們再持續調優。

記得我們在

【邁向圖神經網絡GNN】Part3: 圖神經網絡的核心-訊息傳遞機制

有提到關於 node update 之前 agg 的方法,add 的表現大多會優於 mean 與 max ,因此我們這裡也改成 add ,同時 dropout 再提升 0.05

class myGNN(torch.nn.Module):
def __init__(self, layer_num, input_dim, hidden_dim, output_dim, dropout_rate=0.6, aggr='add'):
super(myGNN, self).__init__()
self.layer_num = layer_num
self.encoder = nn.Linear(input_dim, hidden_dim)
self.bn_layers = nn.ModuleList([nn.BatchNorm1d(hidden_dim) for _ in range(layer_num)])
self.mp_layers = nn.ModuleList([geom_nn.GCNConv(hidden_dim, hidden_dim, aggr=aggr) for _ in range(layer_num)])
self.dropout = dropout_rate
self.decoder = nn.Linear(hidden_dim, output_dim)

def forward(self, x, edge_index):
x = self.encoder(x)
for i in range(self.layer_num):
x = F.relu(x)
x = F.dropout(x, p=self.dropout, training=self.training)
x = self.bn_layers[i](x)
x = self.mp_layers[i](x, edge_index)
x = self.decoder(x)
return x

輸出

Epoch: 001, Loss: 2.0578
Epoch: 002, Loss: 1.8797
Epoch: 003, Loss: 1.8410
Epoch: 004, Loss: 1.7337
Epoch: 005, Loss: 1.6006
Epoch: 006, Loss: 1.5471
Epoch: 007, Loss: 1.4120
Epoch: 008, Loss: 1.4017
Epoch: 009, Loss: 1.3204
Epoch: 010, Loss: 1.2137
Epoch: 070, Loss: 0.2363
Epoch: 071, Loss: 0.1732
Epoch: 072, Loss: 0.2351
Epoch: 073, Loss: 0.1176
Epoch: 074, Loss: 0.1425
Epoch: 075, Loss: 0.2506
Epoch: 076, Loss: 0.2288
Epoch: 077, Loss: 0.1546
Epoch: 078, Loss: 0.1162
Epoch: 079, Loss: 0.2172
Epoch: 080, Loss: 0.1823
Epoch: 081, Loss: 0.1976
Epoch: 082, Loss: 0.1133
Epoch: 083, Loss: 0.1148
Epoch: 084, Loss: 0.1102
Epoch: 085, Loss: 0.1629
Epoch: 086, Loss: 0.2070
Epoch: 087, Loss: 0.2446
Epoch: 088, Loss: 0.1316
Epoch: 089, Loss: 0.1847
Epoch: 090, Loss: 0.1238
Epoch: 091, Loss: 0.1610
Epoch: 092, Loss: 0.1585
Epoch: 093, Loss: 0.0948
Epoch: 094, Loss: 0.1809
Epoch: 095, Loss: 0.1859
Epoch: 096, Loss: 0.0982
Epoch: 097, Loss: 0.1741
Epoch: 098, Loss: 0.2341
Epoch: 099, Loss: 0.1564
Epoch: 100, Loss: 0.1871
Test Accuracy: 0.7330
raw-image

Test acc 明顯提升到 0.7 ,同時可視化效果每一個類別更加分散,還是有零星分錯類別,不過作為 baseline model ,結果顯示 GNN 是有效的。

小結

今天討論了如何使用 PyTorch 框架來構建和訓練圖神經網絡(GNN),並使用 Cora 資料集進行節點分類任務。透過逐步改進模型架構,包括引入批量標準化和獨立的消息傳遞層,以及調整 Dropout 和聚合函數,我們顯著提高了模型的分類準確率。最終實驗表明,經過優化的 GNN 模型在處理圖結構數據具有強大的性能和應用潛力~我們下篇見!

avatar-img
32會員
42內容數
歡迎來到《桃花源記》專欄。這裡不僅是一個文字的集合,更是一個探索、夢想和自我發現的空間。在這個專欄中,我們將一同走進那些隱藏在日常生活中的"桃花源"——那些讓我們心動、讓我們反思、讓我們找到內心平靜的時刻和地方
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
Karen的沙龍 的其他內容
透過這篇文章,我們將瞭解如何使用PyTorch實作圖神經網絡中的訊息傳遞機制,從定義消息傳遞的類別到實作消息傳遞過程。我們也探討了各種不同的消息傳遞機制,並通過對單次和多次傳遞過程的結果,可以看到節點特徵如何逐步傳遞與更新。
本篇文章專注於消息傳遞(message passing)在圖神經網絡(GNN)中的應用,並以簡單的例子解釋了消息傳遞的過程和機制。
本文主要筆記使用pytorch建立graph的幾個概念與實作。在傳統的神經網路模型中,數據點之間往往是互相連接和影響的,使用GNN,我們不僅處理單獨的數據點或Xb,而是處理一個包含多個數據點和它們之間連結的特徵。GNN的優勢在於其能夠將這些連結關係納入模型中,將關係本身作為特徵進行學習。
GNN發展背景 傳統的深度學習模型如在計算機視覺(CV)和自然語言處理(NLP)領域中極為成功,主要是處理結構化數據如影像和文本。這些數據類型通常具有固定且規律的結構,例如影像是由有序的像素點組成。然而,在真實世界中,許多數據是非結構化的,如化合物結構(原子和分子)。這些數據雖然具有一定的規則性,
本文探討了監督式學習、分群和相似度這幾個推薦系統算法,分別討論了它們的優點、缺點以及適用場景。這些算法在推薦系統中扮演著重要角色,並透過特徵選擇與預處理、相似度度量和鄰居的選擇等關鍵因素進行深入分析。文章最後提出在選擇推薦系統算法時應該考慮的因素,以及未來的研究方向。
Kafka是一個先進的分佈式流處理平臺,具有高吞吐量、可擴展性、容錯性和低延遲特性,提供瞭解耦、非同步和削峰特點。本文介紹了Kafka的通訊模式、適合的應用場景和未來發展趨勢,旨在幫助使用者更好地理解和應用Kafka。
透過這篇文章,我們將瞭解如何使用PyTorch實作圖神經網絡中的訊息傳遞機制,從定義消息傳遞的類別到實作消息傳遞過程。我們也探討了各種不同的消息傳遞機制,並通過對單次和多次傳遞過程的結果,可以看到節點特徵如何逐步傳遞與更新。
本篇文章專注於消息傳遞(message passing)在圖神經網絡(GNN)中的應用,並以簡單的例子解釋了消息傳遞的過程和機制。
本文主要筆記使用pytorch建立graph的幾個概念與實作。在傳統的神經網路模型中,數據點之間往往是互相連接和影響的,使用GNN,我們不僅處理單獨的數據點或Xb,而是處理一個包含多個數據點和它們之間連結的特徵。GNN的優勢在於其能夠將這些連結關係納入模型中,將關係本身作為特徵進行學習。
GNN發展背景 傳統的深度學習模型如在計算機視覺(CV)和自然語言處理(NLP)領域中極為成功,主要是處理結構化數據如影像和文本。這些數據類型通常具有固定且規律的結構,例如影像是由有序的像素點組成。然而,在真實世界中,許多數據是非結構化的,如化合物結構(原子和分子)。這些數據雖然具有一定的規則性,
本文探討了監督式學習、分群和相似度這幾個推薦系統算法,分別討論了它們的優點、缺點以及適用場景。這些算法在推薦系統中扮演著重要角色,並透過特徵選擇與預處理、相似度度量和鄰居的選擇等關鍵因素進行深入分析。文章最後提出在選擇推薦系統算法時應該考慮的因素,以及未來的研究方向。
Kafka是一個先進的分佈式流處理平臺,具有高吞吐量、可擴展性、容錯性和低延遲特性,提供瞭解耦、非同步和削峰特點。本文介紹了Kafka的通訊模式、適合的應用場景和未來發展趨勢,旨在幫助使用者更好地理解和應用Kafka。
你可能也想看
Google News 追蹤
Thumbnail
國泰CUBE App 整合外幣換匯、基金、證券等服務,提供簡便、低成本的美股定期定額投資解決方案。 5分鐘開戶、低投資門檻,幫助新手輕鬆進軍國際股市;提供人氣排行榜,讓投資人能夠掌握市場趨勢。
Thumbnail
🐳本篇獲邀 《1111人力銀行》刊登! 石頭哥以一位經理人的視角,今天要分享的是:找一句話,可以鞭策你持續邁向成功的巔峰!
Thumbnail
深陷財務危機的英國第二大城市伯明罕,出現了不少出售市議會資產作為現金週轉的討論,包含博物館、美術館和圖書館,真的可以被賣掉嗎?來聽聽第一線館員怎麼說...
Thumbnail
GoSky AI於2018年3月創立,GoSky AI共同創辦人暨執行長張聿瑋談及進場的時機點很重要,他提到我們這一代恰逢數位世代,Al 人工智慧技術已日趨成熟,應該廣泛運用 Al 科技去幫助更多人圓夢。
Thumbnail
人人都有不同的拍照動機,大部分是為了紀錄、分享或創作。至於修圖的理由又是什麼呢?虛榮?仔細思考,找尋更深層的意義,而後正確追求,生活更加自在快活。
Thumbnail
簡報的靈魂是「重點」;打造重點靠「對比」! 但PPT 不是專業設計軟體, 想把一張照片的某區域, 拉高視覺能見度, 真的不容易辦到! 後來,我才明白,一個有趣的組合: 圖片或材質填滿+ 投影片背景填滿,幫我打開了簡報設計的另一番小天地。
Thumbnail
主動脈瘤是主動脈出現異常膨大,當膨大部位的直徑超過正常主動脈直徑的1.5倍以上,就稱為「主動脈瘤」。國立臺灣大學醫學院附設醫院心臟血管外科吳毅暉醫師指出,主動脈瘤就像氣球一樣,越大越容易破裂;而主動脈瘤一旦破裂了,會導致大量出血,是極度危險的急症。
Thumbnail
腦動脈瘤破裂會引發爆炸性頭痛、頸部僵硬,可能在短時間內昏迷、甚至奪命。若能提早發現、提早治療,有助於改善預後,降低失能的風險!
Thumbnail
寫作與讀書關係非常大。善於寫作的人首先善於讀書,熱愛讀書。而不善於寫作的人,基本上對書沒有多少興趣。 讀書的最佳年齡是兒童青少年時期,這個時期如果熱愛閱讀,就可以保持一輩子。青少年時期不愛讀書,以後能夠愛上讀書的可能性不大。 每個年齡段都有最適合的事情,錯過了就難以彌補。年輕時沒有把最優秀思想裝
Thumbnail
非常開心地受到邀約來到南山微風幫三星NOTE10來做現場似顏繪的活動 一早到現場就被排隊等候的粉絲們嚇到了這次的旗艦機
Thumbnail
國泰CUBE App 整合外幣換匯、基金、證券等服務,提供簡便、低成本的美股定期定額投資解決方案。 5分鐘開戶、低投資門檻,幫助新手輕鬆進軍國際股市;提供人氣排行榜,讓投資人能夠掌握市場趨勢。
Thumbnail
🐳本篇獲邀 《1111人力銀行》刊登! 石頭哥以一位經理人的視角,今天要分享的是:找一句話,可以鞭策你持續邁向成功的巔峰!
Thumbnail
深陷財務危機的英國第二大城市伯明罕,出現了不少出售市議會資產作為現金週轉的討論,包含博物館、美術館和圖書館,真的可以被賣掉嗎?來聽聽第一線館員怎麼說...
Thumbnail
GoSky AI於2018年3月創立,GoSky AI共同創辦人暨執行長張聿瑋談及進場的時機點很重要,他提到我們這一代恰逢數位世代,Al 人工智慧技術已日趨成熟,應該廣泛運用 Al 科技去幫助更多人圓夢。
Thumbnail
人人都有不同的拍照動機,大部分是為了紀錄、分享或創作。至於修圖的理由又是什麼呢?虛榮?仔細思考,找尋更深層的意義,而後正確追求,生活更加自在快活。
Thumbnail
簡報的靈魂是「重點」;打造重點靠「對比」! 但PPT 不是專業設計軟體, 想把一張照片的某區域, 拉高視覺能見度, 真的不容易辦到! 後來,我才明白,一個有趣的組合: 圖片或材質填滿+ 投影片背景填滿,幫我打開了簡報設計的另一番小天地。
Thumbnail
主動脈瘤是主動脈出現異常膨大,當膨大部位的直徑超過正常主動脈直徑的1.5倍以上,就稱為「主動脈瘤」。國立臺灣大學醫學院附設醫院心臟血管外科吳毅暉醫師指出,主動脈瘤就像氣球一樣,越大越容易破裂;而主動脈瘤一旦破裂了,會導致大量出血,是極度危險的急症。
Thumbnail
腦動脈瘤破裂會引發爆炸性頭痛、頸部僵硬,可能在短時間內昏迷、甚至奪命。若能提早發現、提早治療,有助於改善預後,降低失能的風險!
Thumbnail
寫作與讀書關係非常大。善於寫作的人首先善於讀書,熱愛讀書。而不善於寫作的人,基本上對書沒有多少興趣。 讀書的最佳年齡是兒童青少年時期,這個時期如果熱愛閱讀,就可以保持一輩子。青少年時期不愛讀書,以後能夠愛上讀書的可能性不大。 每個年齡段都有最適合的事情,錯過了就難以彌補。年輕時沒有把最優秀思想裝
Thumbnail
非常開心地受到邀約來到南山微風幫三星NOTE10來做現場似顏繪的活動 一早到現場就被排隊等候的粉絲們嚇到了這次的旗艦機