Learning Curves ที่ใช้ในการวิเคราะห์ประสิทธิภาพ Machine Learning Model

Phakorn
10 min readSep 24, 2020

--

Learning Curve

>> เป็นกราฟที่ใช้วิเคราะห์ประสิทธิภาพการเรียนรู้ของ Model จาก Training Dataset ซึ่งแกน x ของกราฟจะเป็นครั้งที่เรียนรู้ (Epoch) และแกน y จะเป็นประสิทธิภาพของ Model โดยประสิทธิภาพของ Model จะถูกวัดหลังจากการปรับปรุง Weight และ Bias ด้วยข้อมูล 2 ชนิด ได้แก่

  • Training Dataset ที่ Model กำลังเรียนรู้
  • Validation Dataset ซึ่งไม่เคยถูกใช้สอน Model มาก่อน

โดยประสิทธิภาพของ Model จะวัดได้จาก Loss และ Accuracy ซึ่งยิ่งค่า Loss หรือ Error น้อยแสดงว่า Model ยิ่งมีการเรียนรู้ที่ดี แต่สำหรับค่า Accuracy จะเป็นในทางตรงกันข้าม คือยิ่งค่า Accuracy มาก แสดงว่า Model ยิ่ง มีการเรียนรู้ที่ดี

Underfit Learning Curve

  • โดยเราจะจำลองสถานการณ์ของ Model ที่มีปัญหาการเรียนรู้แบบ Underfit ด้วยการพัฒนา Model เพื่อทำ Sentiment Analysis จาก IMDB Dataset ซึ่งเป็นคำวิจารณ์ภาพยนตร์ต่างประเทศ

โดย Dataset แรกจะเป็น IMDB

ก่อนอื่นเราจะ Import Library ที่จำเป็นต้องใช้ในการทดลองดังต่อไปนี้

from tensorflow.keras.datasets import imdb
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.optimizers import SGD

from tensorflow.keras.utils import to_categorical
from tensorflow.keras.preprocessing import sequence

import plotly
import plotly.graph_objs as go
import plotly.express as px

from matplotlib import pyplot

import numpy

from sklearn.datasets import make_moons, make_circles, make_blobs
from pandas import DataFrame

from sklearn.model_selection import train_test_split

import pandas as pd

Load Dataset

top_words = 5000
(X_train, y_train), (X_test, y_test)= imdb.load_data(num_words=top_words)
max_words = 500

X_train.shape
imdb.get_word_index()

ต่อ Train และ Test Dataset เพื่อคำนวนคำที่ไม่ซ้ำทั้งหมดใน Comment

X = numpy.concatenate((X_train, X_test), axis=0)
y = numpy.concatenate((y_train, y_test), axis=0)

print("Number of words: ")
print(len(numpy.unique(numpy.hstack(X))))

ดูความยาวของคำในประโยค

print("Review length: ")
result = [len(x) for x in X]
print("Mean %.2f words (%f)" % (numpy.mean(result), numpy.std(result)))

pyplot.boxplot(result)
pyplot.show()

เติม 0 เพื่อทำให้ความยาวของประโยคเท่ากัน (Padding)

X_train = sequence.pad_sequences(X_train, maxlen=max_words)
X_test = sequence.pad_sequences(X_test, maxlen=max_words)

X_train.shape

นิยาม Model

model = Sequential()
model.add(Dense(8, input_dim=max_words, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()

Train Model

history = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=200, batch_size=128, verbose=2)

Plot Loss

plotly.offline.init_notebook_mode(connected=True)

h1 = go.Scatter(y=history.history['loss'],
mode="lines", line=dict(
width=2,
color='blue'),
name="loss"
)
h2 = go.Scatter(y=history.history['val_loss'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_loss"
)

data = [h1,h2]
layout1 = go.Layout(title='Loss',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")

Plot Accuracy

h1 = go.Scatter(y=history.history['accuracy'], 
mode="lines", line=dict(
width=2,
color='blue'),
name="acc"
)
h2 = go.Scatter(y=history.history['val_accuracy'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_acc"
)

data = [h1,h2]
layout1 = go.Layout(title='Accuracy',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")
  • จากกราฟ Loss จะเห็นว่าตั้งแต่ Epoch ที่ 1 ค่า Training Loss จะค่อนข้างราบเรียบ และจากกราฟ Accuracy ค่า Training acc จะค่อนข้างเหวี่ยง แต่ไม่มีแนวโน้มจะลดลงเลย ดังนั้นรูปแบบ Learning Curve ดังกล่าว แสดงว่า Model ของเราเกิดปัญหา Underfit ครับ

Overfit Learning Curve

  • กราฟ Learning Curve แบบ Overfitting จะบ่งบอกว่า Model มีการเรียนรู้ได้จาก Training Dataset ได้ดีเกินไป คือมีการเรียนรู้จาก Noise หรือความผันผวนเกือบทุกรูปแบบจาก Training Dataset

สร้าง Dataset แบบ 2 Class โดยใช้ Function make_circles ของ Sklearn

X, y =  make_circles(n_samples=500, noise=0.2, random_state=1)

แบ่งข้อมูลสำหรับ Train และ Test ด้วยการสุ่มในสัดส่วน 50:50

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, shuffle= True)

X_train.shape, X_test.shape, y_train.shape, y_test.shape

นำ Dataset ส่วนที่ Train มาแปลงเป็น DataFrame โดยเปลี่ยนชนิดข้อมูลใน Column “class” เป็น String เพื่อทำให้สามารถแสดงสีแบบไม่ต่อเนื่องได้ แล้วนำไป Plot

X_train_pd = pd.DataFrame(X_train, columns=['x', 'y'])
y_train_pd = pd.DataFrame(y_train, columns=['class'])

df = pd.concat([X_train_pd, y_train_pd], axis=1)
---------------------------------------------------------------fig = px.scatter(df, x="x", y="y", color="class")
fig.show()

นิยาม Model

model = Sequential()
model.add(Dense(60, input_dim=2, activation='relu'))
model.add(Dense(30, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

Train Model

history = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=500, verbose=1)

Plot Loss

plotly.offline.init_notebook_mode(connected=True)

h1 = go.Scatter(y=history.history['loss'],
mode="lines", line=dict(
width=2,
color='blue'),
name="loss"
)
h2 = go.Scatter(y=history.history['val_loss'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_loss"
)

data = [h1,h2]
layout1 = go.Layout(title='Loss',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")

Plot Accuracy

h1 = go.Scatter(y=history.history['accuracy'], 
mode="lines", line=dict(
width=2,
color='blue'),
name="acc"
)
h2 = go.Scatter(y=history.history['val_accuracy'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_acc"
)

data = [h1,h2]
layout1 = go.Layout(title='Accuracy',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")
  • ในการวิเคราะห์ปัญหา Overfitting เราจะพิจารณาจากกราฟ Loss เป็นหลัก โดยจากกราฟ Loss ด้านบน จะเห็นว่า Training Loss จะลดค่าลงอย่างต่อเนื่องเมื่อมีการ Train มากขึ้น ขณะที่ Validation Loss จะลดลงถึงจุดหนึ่งแล้วมีการเพิ่มค่าขึ้นเรื่อยๆ ตอลดการ Train

Good Fit Learning Curve

  • เป็นเป้าหมายในการ Train Model ซึ่งกราฟแบบ Goog Fitting จะบ่งบอกว่า Model มีการเรียนรู้ที่ดี สามารถนำไป Predict ข้อมูลที่ไม่เคยพบเห็นได้อย่างแม่นยำ หรือเรียกว่า Model มีความเป็น Generalize ต่อ Data ใหม่ๆ (มี Generalization Error น้อย)

สร้าง Dataset แบบ 3 Class โดยใช้ Function make_blobs ของ Sklearn

X, y = make_blobs(n_samples=3000, centers=3, n_features=2, cluster_std=2, random_state=2)

แบ่งข้อมูลสำหรับ Train และ Test ด้วยการสุ่มในสัดส่วน 60:40

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, shuffle= True)

X_train.shape, X_test.shape, y_train.shape, y_test.shape

นำ Dataset ส่วนที่ Train มาแปลงเป็น DataFrame โดยเปลี่ยนชนิดข้อมูลใน Column “class” เป็น String เพื่อทำให้สามารถแสดงสีแบบไม่ต่อเนื่องได้ แล้วนำไป Plot

X_train_pd = pd.DataFrame(X_train, columns=['x', 'y'])
y_train_pd = pd.DataFrame(y_train, columns=['class'])

df = pd.concat([X_train_pd, y_train_pd], axis=1)
df["class"] = df["class"].astype(str)
fig = px.scatter(df, x="x", y="y", color="class")
fig.show()

เราจะเข้ารหัสผลเฉลย แบบ One-Hot Encoding เพื่อที่ว่าเมื่อ Model มีการ Predict ว่าเป็น Class ไหน มันจะให้ค่าความมั่นใจ (Confidence) กลับมาด้วย

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

นิยาม Model

model = Sequential()
model.add(Dense(50, input_dim=2, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(3, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()

Train Model

his = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=200, verbose=1)

Plot Loss

plotly.offline.init_notebook_mode(connected=True)

h1 = go.Scatter(y=his.history['loss'],
mode="lines", line=dict(
width=2,
color='blue'),
name="loss"
)
h2 = go.Scatter(y=his.history['val_loss'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_loss"
)

data = [h1,h2]
layout1 = go.Layout(title='Loss',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")

Plot Accuracy

h1 = go.Scatter(y=his.history['accuracy'], 
mode="lines", line=dict(
width=2,
color='blue'),
name="acc"
)
h2 = go.Scatter(y=his.history['val_accuracy'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_acc"
)

data = [h1,h2]
layout1 = go.Layout(title='Accuracy',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")
  • จากกราฟ Loss ด้านบน จะเห็นว่าทั้ง Training Loss และ Validation Loss จะลดค่าลงอย่างต่อเนื่องจนถึงจุดหนึ่งมันจะคงที่ โดยทั้ง 2 กราฟจะมี Gap ระหว่างกันน้อยมาก ดังนั้นรูปแบบ Learning Curve ดังกล่าว แสดงว่าเป็น Model แบบ Good Fitting หรือเป็น Model ที่มีการเรียนรู้ที่ดี สามารถนำไป Predict ข้อมูลที่ไม่เคยพบเห็นได้อย่างแม่นยำ

Unrepresentative Train Dataset

  • นอกจากเราจะใช้ Learning Curve ในการพิจารณาว่า Model มีประสิทธิภาพดีหรือไม่แล้ว เราสามารถใช้พิจารณาได้ว่า Dataset ที่นำมา Train และ Test เป็นตัวแทนของข้อมูลที่ดีหรือไม่
  • เราจะจำลองสถานการณ์ของ Train Dataset ที่ไม่สามารถเป็นตัวแทนของข้อมูลที่ดี ดังขั้นตอนต่อไปนี้

สร้าง Dataset แบบ 3 Class โดยใช้ Function make_blobs ของ Sklearn

X, y = make_blobs(n_samples=100, centers=3, n_features=2, cluster_std=2, random_state=2)

แบ่งข้อมูลสำหรับ Train และ Test ด้วยการสุ่มในสัดส่วน 50:50

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, shuffle= True)

X_train.shape, X_test.shape, y_train.shape, y_test.shape

นำ Dataset ส่วนที่ Train มาแปลงเป็น DataFrame โดยเปลี่ยนชนิดข้อมูลใน Column “class” เป็น String เพื่อทำให้สามารถแสดงสีแบบไม่ต่อเนื่องได้ แล้วนำไป Plot

X_train_pd = pd.DataFrame(X_train, columns=['x', 'y'])
y_train_pd = pd.DataFrame(y_train, columns=['class'])

df = pd.concat([X_train_pd, y_train_pd], axis=1)
df["class"] = df["class"].astype(str)
fig = px.scatter(df, x="x", y="y", color="class")
fig.show()

เข้ารหัสผลเฉลย แบบ One-Hot Encoding เพื่อที่ว่าเมื่อ Model มีการ Predict ว่าเป็น Class ไหน มันจะให้ค่าความมั่นใจ (Confidence) กลับมาด้วย

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

นิยาม Model

model = Sequential()
model.add(Dense(50, input_dim=2, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(3, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

Train Model

his = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=200, verbose=1)

Plot Loss

plotly.offline.init_notebook_mode(connected=True)

h1 = go.Scatter(y=his.history['loss'],
mode="lines", line=dict(
width=2,
color='blue'),
name="loss"
)
h2 = go.Scatter(y=his.history['val_loss'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_loss"
)

data = [h1,h2]
layout1 = go.Layout(title='Loss',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")

Plot Accuracy

h1 = go.Scatter(y=his.history['accuracy'], 
mode="lines", line=dict(
width=2,
color='blue'),
name="acc"
)
h2 = go.Scatter(y=his.history['val_accuracy'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_acc"
)

data = [h1,h2]
layout1 = go.Layout(title='Accuracy',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")
  • จากกราฟ Loss และ Accuracy พบว่าทั้ง 2 ค่ามีแนวโน้มลดลงเรื่อยๆ เมื่อมีการ Train จำนวนมากขึ้น แต่มี Gap ระหว่าง Training Loss กับ Validation Loss และ Training Accuracy กับ Validation Accuracy สูง แสดงว่าเรามี Training Dataset น้อย ไม่เพียงพอในการ Train Model

Unrepresentative Validation Dataset

  • เราจะจำลองสถานการณ์ของ Validation Dataset ที่ไม่สามารถเป็นตัวแทนของข้อมูลที่ดี ใน 2 สถานการณ์

++ สถานการณ์ที่ 1 Validate น้อย และไม่สามารถเป็นตัวแทนของ validation dataset ได้

++ สถานการณ์ที่ 2 Validate น้อย และง่ายเกินไป

สถานการณ์ที่ 1 มีขั้นตอนการทดลองดังต่อไปนี้

สร้าง Dataset แบบ 3 Class โดยใช้ Function make_blobs ของ Sklearn

X, y = make_blobs(n_samples=500, centers=3, n_features=2, cluster_std=10, random_state=2)

แบ่งข้อมูลสำหรับ Train และ Test ด้วยการสุ่มในสัดส่วน 95:5

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.05, shuffle= True)

X_train.shape, X_test.shape, y_train.shape, y_test.shape

นำ Dataset ส่วนที่ Train มาแปลงเป็น DataFrame โดยเปลี่ยนชนิดข้อมูลใน Column “class” เป็น String เพื่อทำให้สามารถแสดงสีแบบไม่ต่อเนื่องได้ แล้วนำไป Plot

X_train_pd = pd.DataFrame(X_train, columns=['x', 'y'])
y_train_pd = pd.DataFrame(y_train, columns=['class'])

df = pd.concat([X_train_pd, y_train_pd], axis=1)
df["class"] = df["class"].astype(str)
fig = px.scatter(df, x="x", y="y", color="class")
fig.show()

เข้ารหัสผลเฉลย แบบ One-Hot Encoding เพื่อที่ว่าเมื่อ Model มีการ Predict ว่าเป็น Class ไหน มันจะให้ค่าความมั่นใจ (Confidence) กลับมาด้วย

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

นิยาม Model

model = Sequential()
model.add(Dense(50, input_dim=2, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(3, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

Train Model

his = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=200, verbose=1)

Plot Loss

plotly.offline.init_notebook_mode(connected=True)

h1 = go.Scatter(y=his.history['loss'],
mode="lines", line=dict(
width=2,
color='blue'),
name="loss"
)
h2 = go.Scatter(y=his.history['val_loss'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_loss"
)

data = [h1,h2]
layout1 = go.Layout(title='Loss',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")

Plot Accuracy

h1 = go.Scatter(y=his.history['accuracy'], 
mode="lines", line=dict(
width=2,
color='blue'),
name="acc"
)
h2 = go.Scatter(y=his.history['val_accuracy'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_acc"
)

data = [h1,h2]
layout1 = go.Layout(title='Accuracy',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")

สถานการณ์ที่ 2 มีขั้นตอนการทดลองดังต่อไปนี้

สร้าง Dataset แบบ 3 Class โดยใช้ Function make_blobs ของ Sklearn

X, y = make_blobs(n_samples=500, centers=3, n_features=2, cluster_std=2, random_state=2)

แบ่งข้อมูลสำหรับ Train และ Test ด้วยการสุ่มในสัดส่วน 97:3

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.03, shuffle= True)

X_train.shape, X_test.shape, y_train.shape, y_test.shape

นำ Dataset ส่วนที่ Train มาแปลงเป็น DataFrame โดยเปลี่ยนชนิดข้อมูลใน Column “class” เป็น String เพื่อทำให้สามารถแสดงสีแบบไม่ต่อเนื่องได้ แล้วนำไป Plot

X_train_pd = pd.DataFrame(X_train, columns=['x', 'y'])
y_train_pd = pd.DataFrame(y_train, columns=['class'])

df = pd.concat([X_train_pd, y_train_pd], axis=1)
df["class"] = df["class"].astype(str)
fig = px.scatter(df, x="x", y="y", color="class")
fig.show()

เข้ารหัสผลเฉลย แบบ One-Hot Encoding เพื่อที่ว่าเมื่อ Model มีการ Predict ว่าเป็น Class ไหน มันจะให้ค่าความมั่นใจ (Confidence) กลับมาด้วย

y_train = to_categorical(y_train)
y_test = to_categorical(y_test)

นิยาม Model

model = Sequential()
model.add(Dense(50, input_dim=2, activation='relu', kernel_initializer='he_uniform'))
model.add(Dense(3, activation='softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

Train Model

his = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=200, verbose=1)

Plot Loss

plotly.offline.init_notebook_mode(connected=True)

h1 = go.Scatter(y=his.history['loss'],
mode="lines", line=dict(
width=2,
color='blue'),
name="loss"
)
h2 = go.Scatter(y=his.history['val_loss'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_loss"
)

data = [h1,h2]
layout1 = go.Layout(title='Loss',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")

Plot Accuracy

h1 = go.Scatter(y=his.history['accuracy'], 
mode="lines", line=dict(
width=2,
color='blue'),
name="acc"
)
h2 = go.Scatter(y=his.history['val_accuracy'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_acc"
)

data = [h1,h2]
layout1 = go.Layout(title='Accuracy',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")

Dataset ที่ 2 จะเป็น reuters

  • จะแนะนำวิธีที่ใช้งานได้สะดวกที่สุด คือ Good Fit Learning Curve

โหลด Dataset

top_words = 5000
(X_train, y_train), (X_test, y_test) = reuters.load_data(num_words=top_words)
max_words = 500

X_train.shape

นิยาม Model

model = Sequential()
model.add(Dense(8, input_dim=max_words, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
model.summary()

Train Model

his = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=200, batch_size=128, verbose=2)

Plot Loss

plotly.offline.init_notebook_mode(connected=True)

h1 = go.Scatter(y=his.history['loss'],
mode="lines", line=dict(
width=2,
color='blue'),
name="loss"
)
h2 = go.Scatter(y=his.history['val_loss'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_loss"
)

data = [h1,h2]
layout1 = go.Layout(title='Loss',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")

Plot Accuracy

h1 = go.Scatter(y=his.history['accuracy'], 
mode="lines", line=dict(
width=2,
color='blue'),
name="acc"
)
h2 = go.Scatter(y=his.history['val_accuracy'],
mode="lines", line=dict(
width=2,
color='red'),
name="val_acc"
)

data = [h1,h2]
layout1 = go.Layout(title='Accuracy',
xaxis=dict(title='epochs'),
yaxis=dict(title=''))
fig1 = go.Figure(data = data, layout=layout1)
plotly.offline.iplot(fig1, filename="Intent Classification")

สำหรับครั้งนี้ก็มรเท่านี้ครับ

***Thank You For Watching****

--

--

No responses yet

Write a response