Sử dụng scipy.optimize.linprog để giải bài toán trên.. Sử dụng cvxpy để giải bài toán trên.. Sử dụng thuật toán Gradient Descent, hãy tìm giá trị của để tối ưu hóa hàm số với giá trị ba
Trang 1ĐỀ THI GIỮA KÌ
Môn: Tối ưu hoá cho Khoa học dữ liệu
Ngày: 28/10/2023
Lớp: DHKHDL17A Thời gian: 90 phút
Câu 1 (3 điểm)
Một cơ sở sản xuất đồ gỗ dự định sản xuất ba loại sản phẩm là bàn, ghế và tủ Định mức sử dụng lao động, chi phí sản xuất và giá bán mỗi sản phẩm mỗi loại ước tính trong bảng sau:
Lao động (ngày công) 2 1 3 Chi phí sản xuất (ngàn đồng) 100 40 250 Giá bán (ngàn đồng) 260 120 600 Bài toán đặt ra là xác định số sản phẩm mỗi loại cần phải sản xuất sao cho không bị động trong sản xuất và tổng doanh thu đạt được cao nhất, biết rằng cơ sở có số lao động tương đương với 500 ngày công, số tiền dành cho chi phí sản xuất là 40 triệu đồng và số bàn, ghế phải theo tỉ lệ 1/6
1 Hãy lập mô hình tối ưu của bài toán trên theo dạng dưới đây bằng cách chỉ ra
và
3 Sử dụng scipy.optimize.linprog để giải bài toán trên
4 Sử dụng cvxpy để giải bài toán trên
Lưu ý: Chấp nhận số lượng bàn ghế là số thực.
Bài toán mẫu Giả sử chúng ta có bài toán tối ưu hóa tuyến tính sau:
Hàm mục tiêu: Minimize
f0, A, b h
minimize f0(x), subject to Ax ≤ b,
h(x) = 0.
(1) (2) (3)
f0(x) = −260x1− 120x2− 600x3 (4)
Trang 2(Chúng ta sử dụng dấu trừ vì linprog trong scipy chỉ hỗ trợ tối thiểu hóa.) x- _2 \leq -4 )
( x_2 \geq -số)+ Bước 1: Xác định các tham số Hệ s+ ố hàm mục tiêu: ( c = [-1, 4] ) Ma trận ràng b+ uộc: ( A = [[3, -1], [-1, -2]] )
Vector ràng buộc: ( b = [6, -4] ) Giới hạn biến: ( x_1 ) không giới hạn, ( x_2 \geq -3 )_2
\geq -3 )
\section*{Mô hình tối ưu}
Giả sử số lượng bàn, ghế và tủ cần sản xuất lần lượt là (x_1), (x_2) và (x_3)
\subsection*{Hàm mục tiêu} Chúng ta cần tối đa hóa tổng doanh thu: [ f_0(x) = - (260x_1 + 120x_2 + 600x_3) ] (Chúng ta sử dụng dấu trừ vì \texttt{scipy.optimize.linprog} chỉ hỗ trợ
hàm mục tiêu dạng tối thiểu hóa.)
\subsection*{Ràng buộc}
1 Ràng buộc về lao động: [ 2x_1 + x_2 + 3x_3 \leq 500 ]
2 Ràng buộc về chi phí sản xuất: [ 100x_1 + 40x_2 + 250x_3 \leq 40000 ]
3 Ràng buộc về tỉ lệ bàn và ghế: [ x_1 = \frac{1}{6}x_2 ]
4 Ràng buộc không âm: [ x_1 \geq 0, \quad x_2 \geq 0, \quad x_3 \geq 0 ]
\subsection*{Mô hình toán học}
ad x_3 \geq 0 \end{align}
\end{document}
2) Sử dụng scipy.optimize
from scipy.optimize import linprog
# Hệ số cho hàm mục tiêu (tối đa hóa doanh thu, nên ta tối thiểu hóa nghịch đảo của
# Do x2 = 6 * x1, hệ số cho x1 được điều chỉnh tương ứng
c = [ 260, - 120, -600] # Hệ số cho x1 và x3
# Hệ số cho các ràng buộc bất đẳng thức (ma trận A và vector b)
# Ràng buộc lao động: 8*x1 + 3*x3 <= 500
# Ràng buộc chi phí: 340*x1 + 250*x3 <= 40000
A = [
minimize − (260x1 + 120x2+ 600x3),
subject to 2x1+ x2+ 3x3 ≤ 500,
100x1+ 40x2+ 250x3 ≤ 40000,
x1− x2 = 0,
x1 ≥ 0, x2 ≥ 0, x3 ≥ 0.
(5) (6) (7) (8) (9)
1 6
In [1]:
Trang 3[ , 1 ], # Ràng buộc về lao động
[100, 40, 250] # Ràng buộc về chi phí sản xuất
]
# Véc tơ b đại diện cho các giới hạn bên phải của ràng buộc bất đẳng thức
b = [500, 40000]
# Giới hạn cho x1 và x3 (số lượng sản phẩm không âm)
x_bounds = ( , None)
# Giải bài toán lập trình tuyến tính cho bài toán rút gọn
result = linprog( , A_ub= , b_ub= , bounds= x_bounds, x_bounds], method='highs')
# Lấy giá trị của x1 (số lượng bàn) và x3 (số lượng tủ)
x1 = result. [ ] # số lượng bàn
x3 = result. [ ] # số lượng tủ
x2 = 6 * x1 # số lượng ghế (vì x2 = 6 * x1)
# Tính tổng doanh thu
total_revenue = - result.fun)
# Hiển thị kết quả
x1, x2, x3, total_revenue
(5.102040816326523, 30.61224489795914, 153.06122448979593, 96836.73469387754)
from scipy.optimize import linprog
# Hệ số hàm mục tiêu
c = [ 1 ]
# Ma trận và vector ràng buộc
A = [[3 1], - , - ]]
b = [ , - ]
# Giới hạn biến
x0_bounds = (None, None)
x1_bounds = ( 3 None)
# Giải bài toán
res = linprog( , A_ub= , b_ub= , bounds= x0_bounds, x1_bounds])
# Kết quả
print("Giá trị tối ưu:", res.fun)
print("Giá trị của các biến:", res. )
Giá trị tối ưu: 1.1428571428571415
Giá trị của các biến: [2.28571429 0.85714286]
3) Sử dụng cvxpy
import cvxpy as cp
# Khai báo biến quyết định
x1 = cp.Variable(nonneg= True) # số lượng bàn (không âm)
Out[1]:
In [5]:
In [2]:
Trang 4x3 = cp.Variable(nonneg= True) # số lượng tủ (không âm)
x2 = 6 * x1 # số lượng ghế, đã biết tỷ lệ x2 = 6 * x1
# Hàm mục tiêu (tối đa hóa doanh thu, tức là tối thiểu hóa nghịch đảo của nó)
objective = cp.Maximize(260 x1 + 120 x2 + 600 x3)
# Ràng buộc:
constraints = [
8 * x1 + 3 * x3 <= 500, # Ràng buộc về lao động
340 x1 + 250 x3 <= 40000 # Ràng buộc về chi phí sản xuất
]
# Xây dựng bài toán
problem = cp.Problem(objective, constraints)
# Giải bài toán
problem.solve()
# Lấy giá trị kết quả
x1_value = x1.value
x3_value = x3.value
x2_value = 6 * x1_value # Số lượng ghế
total_revenue = 260 x1_value + 120 x2_value + 600 x3_value
# In kết quả
print(f"Số lượng bàn: {x1_value:.2f}")
print(f"Số lượng ghế: {x2_value:.2f}")
print(f"Số lượng tủ: {x3_value:.2f}")
print(f"Tổng doanh thu: {total_revenue:.2f} ngàn đồng")
Số lượng bàn: 5.10
Số lượng ghế: 30.61
Số lượng tủ: 153.06
Tổng doanh thu: 96836.73 ngàn đồng
Câu 2 (4 điểm)
Trang 61 Cho một hàm số mục tiêu Hãy tính đạo hàm của hàm
số này
2 Sử dụng thuật toán Gradient Descent, hãy tìm giá trị của để tối ưu hóa hàm số
với giá trị ban đầu là , sử dụng learning rate là và thực hiện tối đa vòng lặp In ra giá trị của và tương ứng sau mỗi vòng lặp
3 Bằng cách thay đổi giá trị learning rate trong thuật toán trên, hãy giải thích sự quan trọng của việc điều chỉnh tham số learning rate trong thuật toán Gradient Descent và cách lựa chọn giá trị tối ưu của nó
4 Hãy trình bày một ví dụ cụ thể về một vấn đề thực tế trong học máy hoặc khoa học dữ liệu mà Gradient Descent có thể được sử dụng để giải quyết
Code mẫu (câu 2.1, 2.2):
import sympy as sp
# Khai báo biến
f(x) = x2+ sin( ) + 2023x x 2
x f(x) = x2+ sin( ) + 2023x, x
In [17]:
Trang 7x = sp.symbols('x')
x_2 = sp.symbols('x_2')
# Định nghĩa hàm
f = 2 * sp.exp( x) + (x - 2
# Tìm đạo hàm của hàm số
f_prime = sp.diff( , x)
print("Sau khi đạo hàm: ", f_prime)
Sau khi đạo hàm: 4*exp(2*x) + 1
Câu 1, 2:
import numpy as np
import sympy as sp
# 1 Tính đạo hàm của hàm số f(x)
x = sp.symbols('x')
f = x**2 + sp.sin( / ) + 2023*
f_prime = sp.diff( , x)
print(f"Đạo hàm của hàm số f(x): {f_prime}")
# 2 Sử dụng thuật toán Gradient Descent để tối ưu hóa hàm số f(x)
def objective_function( ):
return x**2 + np.sin( / ) + 2023*
def gradient( ):
return *x + 0.5*np.cos( / ) + 2023
def gradient_descent(learning_rate, max_iterations, initial_x):
x = initial_x
for i in range(max_iterations):
grad = gradient( )
x = x - learning_rate * grad
print(f"Vòng lặp {i 1}: x = {x}, f(x) = {objective_function( )}") return x
learning_rate = 0.9
max_iterations = 100
initial_x = 2024
final_x = gradient_descent(learning_rate, max_iterations, initial_x) print("Giá trị x cuối cùng sau Gradient Descent:", final_x)
print("Giá trị f(x) tương ứng:", objective_function(final_x))
In [17]:
Trang 8Đạo hàm của hàm số f(x): 2*x + cos(x/2)/2 + 2023
Vòng lặp 1: x = -3440.31321113998, f(x) = 4876002.355559468 Vòng lặp 2: x = 931.4901692736894, f(x) = 2752079.257805251 Vòng lặp 3: x = -2566.2090665245314, f(x) = 1393987.059267939 Vòng lặp 4: x = 232.162007539132, f(x) = 523563.096265053
Vòng lặp 5: x = -2005.9852059053846, f(x) = -34130.69099537283 Vòng lặp 6: x = -215.60633475570125, f(x) = -389686.3591102944 Vòng lặp 7: x = -1648.4622122708645, f(x) = -617412.2961790441 Vòng lặp 8: x = -502.12066657322, f(x) = -763664.6807625607 Vòng lặp 9: x = -1419.437512399157, f(x) = -856718.9584847123 Vòng lặp 10: x = -685.5823175434986, f(x) = -916909.5642730244 Vòng lặp 11: x = -1271.812606777561, f(x) = -955370.5615278275 Vòng lặp 12: x = -803.368298704932, f(x) = -979813.0192386736 Vòng lặp 13: x = -1178.41255479367, f(x) = -995271.4614540564 Vòng lặp 14: x = -878.040607323064, f(x) = -1005320.1212940649 Vòng lặp 15: x = -1118.580169839656, f(x) = -1011666.1737115162 Vòng lặp 16: x = -926.2841780703264, f(x) = -1015869.5430308301 Vòng lặp 17: x = -1079.5644559419975, f(x) = -1018498.9387677168 Vòng lặp 18: x = -957.4268752629223, f(x) = -1020209.2760526179 Vòng lặp 19: x = -1054.925180804365, f(x) = -1021246.184386634 Vòng lặp 20: x = -977.1863017178842, f(x) = -1021953.8229584643 Vòng lặp 21: x = -1038.984898317487, f(x) = -1022375.9260968424 Vòng lặp 22: x = -989.3199466041582, f(x) = -1022639.3051370879 Vòng lặp 23: x = -1029.1808608304812, f(x) = -1022819.0473977497 Vòng lặp 24: x = -997.7187208550102, f(x) = -1022942.9346090235 Vòng lặp 25: x = -1022.1678426275174, f(x) = -1023019.286263373 Vòng lặp 26: x = -1002.7209567757886, f(x) = -1023054.2163696628 Vòng lặp 27: x = -1018.6460586155096, f(x) = -1023081.5594234045 Vòng lặp 28: x = -1006.200209119156, f(x) = -1023104.5929272005 Vòng lặp 29: x = -1016.1459532533554, f(x) = -1023109.9040015339 Vòng lặp 30: x = -1008.075114059658, f(x) = -1023121.502524345 Vòng lặp 31: x = -1014.3240395173099, f(x) = -1023123.2957792892 Vòng lặp 32: x = -1009.1490777837269, f(x) = -1023127.6629079144 Vòng lặp 33: x = -1013.2268912344041, f(x) = -1023128.5387313559 Vòng lặp 34: x = -1009.8105111197456, f(x) = -1023130.1734297143 Vòng lặp 35: x = -1012.5687620980149, f(x) = -1023130.6389192517 Vòng lặp 36: x = -1010.2475101332634, f(x) = -1023131.3043395774 Vòng lặp 37: x = -1012.150017316939, f(x) = -1023131.5524758262 Vòng lặp 38: x = -1010.5473364585363, f(x) = -1023131.841696068 Vòng lặp 39: x = -1011.8722283423956, f(x) = -1023131.9722030445 Vòng lặp 40: x = -1010.7566011179829, f(x) = -1023132.1033981845 Vòng lặp 41: x = -1011.6834842348153, f(x) = -1023132.1710241633 Vòng lặp 42: x = -1010.9036747607828, f(x) = -1023132.2321974612 Vòng lặp 43: x = -1011.5535123327104, f(x) = -1023132.2667962252 Vòng lặp 44: x = -1011.0072771064323, f(x) = -1023132.2958379161 Vòng lặp 45: x = -1011.4633277908058, f(x) = -1023132.3133632393 Vòng lặp 46: x = -1011.0802808614211, f(x) = -1023132.3273165574 Vòng lặp 47: x = -1011.4004721125096, f(x) = -1023132.3361271474 Vòng lặp 48: x = -1011.1317021399092, f(x) = -1023132.3428854223 Vòng lặp 49: x = -1011.356546562623, f(x) = -1023132.3472904076 Vòng lặp 50: x = -1011.1678996468509, f(x) = -1023132.3505818162 Vòng lặp 51: x = -1011.3257991700891, f(x) = -1023132.3527753649 Vòng lặp 52: x = -1011.1933657749264, f(x) = -1023132.3543844117 Vòng lặp 53: x = -1011.304253685315, f(x) = -1023132.3554736058 Vòng lặp 54: x = -1011.2112733659412, f(x) = -1023132.3562622666 Vòng lặp 55: x = -1011.2891458718407, f(x) = -1023132.3568019966
Trang 9Vòng lặp 56: x = -1011.223861097511, f(x) = -1023132.3571892543 Vòng lặp 57: x = -1011.2785473768732, f(x) = -1023132.3574563205 Vòng lặp 58: x = -1011.2327068448959, f(x) = -1023132.3576467169 Vòng lặp 59: x = -1011.2711100036126, f(x) = -1023132.3577787301 Vòng lặp 60: x = -1011.2389217004651, f(x) = -1023132.3578724217 Vòng lặp 61: x = -1011.2658898246146, f(x) = -1023132.3579376299 Vòng lặp 62: x = -1011.2432874818517, f(x) = -1023132.3579837629 Vòng lặp 63: x = -1011.2622253363916, f(x) = -1023132.3580159559 Vòng lặp 64: x = -1011.24635400266, f(x) = -1023132.3580386812 Vòng lặp 65: x = -1011.259652665685, f(x) = -1023132.3580545695 Vòng lặp 66: x = -1011.248507757929, f(x) = -1023132.3580657674 Vòng lặp 67: x = -1011.2578463864658, f(x) = -1023132.3580736065 Vòng lặp 68: x = -1011.2500203542262, f(x) = -1023132.3580791258 Vòng lặp 69: x = -1011.2565781321813, f(x) = -1023132.3580829928 Vòng lặp 70: x = -1011.2510826193268, f(x) = -1023132.3580857135 Vòng lặp 71: x = -1011.2556876150213, f(x) = -1023132.3580876207 Vòng lặp 72: x = -1011.2518286057776, f(x) = -1023132.3580889622 Vòng lặp 73: x = -1011.2550623150767, f(x) = -1023132.3580899029 Vòng lặp 74: x = -1011.2523524722607, f(x) = -1023132.3580905639 Vòng lặp 75: x = -1011.2546232371644, f(x) = -1023132.3580910279 Vòng lặp 76: x = -1011.2527203507609, f(x) = -1023132.358091354 Vòng lặp 77: x = -1011.2543149185337, f(x) = -1023132.3580915827 Vòng lặp 78: x = -1011.2529786862464, f(x) = -1023132.3580917437 Vòng lặp 79: x = -1011.2540984167708, f(x) = -1023132.3580918564 Vòng lặp 80: x = -1011.2531600960765, f(x) = -1023132.3580919355 Vòng lặp 81: x = -1011.2539463880807, f(x) = -1023132.3580919912 Vòng lặp 82: x = -1011.2532874861312, f(x) = -1023132.3580920305 Vòng lặp 83: x = -1011.253839632303, f(x) = -1023132.3580920579 Vòng lặp 84: x = -1011.2533769419914, f(x) = -1023132.3580920772 Vòng lặp 85: x = -1011.2537646673226, f(x) = -1023132.3580920906 Vòng lặp 86: x = -1011.253439759551, f(x) = -1023132.3580921002 Vòng lặp 87: x = -1011.2537120260571, f(x) = -1023132.3580921068 Vòng lặp 88: x = -1011.2534838711312, f(x) = -1023132.3580921115 Vòng lặp 89: x = -1011.2536750607089, f(x) = -1023132.3580921148 Vòng lặp 90: x = -1011.2535148470126, f(x) = -1023132.3580921171 Vòng lặp 91: x = -1011.2536491031588, f(x) = -1023132.3580921188 Vòng lặp 92: x = -1011.2535365987716, f(x) = -1023132.3580921197 Vòng lặp 93: x = -1011.2536308754156, f(x) = -1023132.3580921206 Vòng lặp 94: x = -1011.2535518731956, f(x) = -1023132.3580921213 Vòng lặp 95: x = -1011.2536180756417, f(x) = -1023132.3580921215 Vòng lặp 96: x = -1011.2535625991301, f(x) = -1023132.3580921219 Vòng lặp 97: x = -1011.2536090874603, f(x) = -1023132.3580921221 Vòng lặp 98: x = -1011.253570131043, f(x) = -1023132.3580921222 Vòng lặp 99: x = -1011.2536027758312, f(x) = -1023132.3580921224 Vòng lặp 100: x = -1011.2535754200651, f(x) = -1023132.3580921224 Giá trị x cuối cùng sau Gradient Descent: -1011.2535754200651 Giá trị f(x) tương ứng: -1023132.3580921224
import numpy as np
# Hàm số mục tiêu
def objective_function( ):
return None
# Đạo hàm của hàm số mục tiêu
In [11]:
Trang 10def gradient( ):
return None
def gradient_descent(learning_rate, max_iterations, initial_x):
return None
learning_rate = 0.9
max_iterations = 100
initial_x = 2024
final_x = gradient_descent(learning_rate, max_iterations, initial_x)
print("Giá trị x cuối cùng sau Gradient Descent:", final_x)
print("Giá trị f(x) tương ứng:", objective_function(final_x))
Giá trị x cuối cùng sau Gradient Descent: None
Giá trị f(x) tương ứng: None
Câu 3:
Learning rate (tốc độ học) là một tham số quan trọng trong thuật toán Gradient Descent,
quyết định kích thước của bước di chuyển trong không gian tham số để tìm cực tiểu của hàm mục tiêu Việc lựa chọn giá trị learning rate phù hợp là rất quan trọng vì:
L Learning rate quá lớn: Nếu learning rate quá lớn, thuật toán có thể bỏ qua điểm cực
tiểu và dao động xung quanh nó hoặc thậm chí phân kỳ, dẫn đến việc không hội t
Learning rate quá nhỏ: Nếu learning rate quá nhỏ, thuật toán sẽ tiến rất chậm và cần
nhiều vòng lặp để hội tụ, làm tăng thời gian tính toán
Câu 1 (3 điểm) Một công ty điện tử sản xuất hai kiểu radio trên hai dây chuyền độc lập Radio kiểu một sản xuất trên dây chuyền một với công suất 45 radio/ngày, radio kiểu hai sản xuất trên dây chuyền hai với công suất 80 radio/ngày Để sản xuất một chiếc radio kiểu một cần 12 linh kiện, để sản xuất một chiếc radio kiểu hai cần 9 linh kiện Tiền lãi khi bán một chiếc radio kiểu một là 250000 đồng, lãi thu được khi bán một chiếc radio kiểu hai là 180000 đồng Biết rằng số linh kiện có thể sử dụng tối đa trong một ngày là 900 Bài toán đặt ra là xác định lợi nhuận có thể thu được lớn nhất của công ty là bao nhiêu a ) (1 điểm) Hãy lập
mô hình tối ưu của bài toán trên theo dạng dưới đây, bằng cách chỉ ra hàm mục tiêu fo, ma trận A và vector b minimize fo(x), subject to Ax < b.b20) (2 điểm) Sử dụng thư viện thích hợp
để giải bài toán trê
Câu 2: Cho ma trận A = [(1,0),(0,-2)] và vector b = (2;4) Xét bài toán tối ưu sau:
min_{x=(x_1,x_2) thuộc R^2} f(x) = e^(2*x_1) + (frac{1}{2}) *||Ax -b||^2_2
a) (2 điểm) Xác định điểm tối ưu x^* và giá trị tối ưu p^* của bài toán (1) b) (2 điểm) Sử dụng thuật toán Gradient Descent, với giá trị x ban đầu là x^(0)=(-3; 5) sử dụng learning rate lần lượt là 2/5 và 1/2 và thực hiện tối đa 100 vòng lặp In ra giá trị của x^(k), f(x^(k)) tương