Print Stack Elements from Bottom to Top

Given a stack s, the task is to print the elements of the stack from bottom to top, such that the elements are still present in the stack without their order being changed in the stack.

Examples:

Input : 
       
       
|   4    |
|   3    |
|   2    |
|   1    |
|________|

Output :1 2 3 4

Approach 1 (Recursion):The idea is to pop the element of the stack and call the recursive function PrintStack. Once the stack becomes empty start printing the element which was popped last and the last element that was popped was the bottom-most element. Thus elements will be printed from bottom to top. Now push back the element that was printed, this will preserve the order of the elements in the stack.

Below is the implementation of the above approach:

#software development #programming #code #coding

What is GEEK

Buddha Community

Print Stack Elements from Bottom to Top
渚  直樹

渚 直樹

1636598700

Pythonでリストを昇順および降順でソートする

リストを昇順および降順でソートするためのPythonプログラム。このPythonチュートリアルでは、リストの要素をPythonで昇順と降順で並べ替える方法を紹介します。

pythonの組み込みメソッド名sort()を使用します。これは、リストの要素/オブジェクトを昇順および降順で並べ替えるために使用されます。

ソートメソッドの基本構文:

 list.sort()

リストを昇順および降順でソートするためのPythonプログラム

  • リスト要素を昇順でソートするPythonプログラム
  • リスト要素を降順でソートするPythonプログラム

リスト要素を昇順でソートするPythonプログラム

# List of integers
num = [100, 200, 500, 600, 300]
 
# sorting and printing 
num.sort()
 
#print
print(num)
 
# List of float numbers
fnum = [100.43, 50.72, 90.65, 16.00, 04.41]
 
# sorting and printing
fnum.sort()
 
#print
print(fnum)
 
# List of strings 
str = ["Test", "My", "Word", "Tag", "Has"]
 
# sorting and  printing
str.sort()
 
#print
print(str)

Pythonプログラムを実行すると、出力は次のようになります。

[100、200、300、500、600]
[4.41、16.0、50.72、90.65、100.43]
['Has'、 'My'、 'Tag'、 'Test'、 'Word']

上で知っているように、リスト要素を昇順で並べ替える方法。次に、sort()メソッドを使用してリストを降順で並べ替える方法を説明します。

sort()メソッドを使用して引数としてreverse = Trueを渡し、リスト要素を降順で並べ替えます。

リスト要素を降順でソートする次のプログラムを見ることができます。

リスト要素を降順でソートするPythonプログラム

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# List of integers
num = [100, 200, 500, 600, 300]
 
# sorting and printing 
num.sort(reverse=True)
 
#print
print(num)
 
# List of float numbers
fnum = [100.43, 50.72, 90.65, 16.00, 04.41]
 
# sorting and printing
fnum.sort(reverse=True)
 
#print
print(fnum)
 
# List of strings 
str = ["Test", "My", "Word", "Tag", "Has"]
 
# sorting and  printing
str.sort(reverse=True)
 
#print
print(str)

プログラムの実行後、出力は次のようになります。

[600、500、300、200、100] 
[100.43、90.65、50.72、16.0、4.41] 
['Word'、 'Test'、 'Tag'、 'My'、 'Has']

リンク: https://www.tutsmake.com/python-program-to-sort-list-in-ascending-and-descending-order/

#python 

Duong Tran

Duong Tran

1646796864

Sắp Xếp Danh Sách Trong Python Với Python.sort ()

Trong bài viết này, bạn sẽ học cách sử dụng phương pháp danh sách của Python sort().

Bạn cũng sẽ tìm hiểu một cách khác để thực hiện sắp xếp trong Python bằng cách sử dụng sorted()hàm để bạn có thể thấy nó khác với nó như thế nào sort().

Cuối cùng, bạn sẽ biết những điều cơ bản về sắp xếp danh sách bằng Python và biết cách tùy chỉnh việc sắp xếp để phù hợp với nhu cầu của bạn.

Phương pháp sort() - Tổng quan về cú pháp

Phương pháp sort() này là một trong những cách bạn có thể sắp xếp danh sách trong Python.

Khi sử dụng sort(), bạn sắp xếp một danh sách tại chỗ . Điều này có nghĩa là danh sách ban đầu được sửa đổi trực tiếp. Cụ thể, thứ tự ban đầu của các phần tử bị thay đổi.

Cú pháp chung cho phương thức sort() này trông giống như sau:

list_name.sort(reverse=..., key=... )

Hãy chia nhỏ nó:

  • list_name là tên của danh sách bạn đang làm việc.
  • sort()là một trong những phương pháp danh sách của Python để sắp xếp và thay đổi danh sách. Nó sắp xếp các phần tử danh sách theo thứ tự tăng dần hoặc giảm dần .
  • sort()chấp nhận hai tham số tùy chọn .
  • reverse là tham số tùy chọn đầu tiên. Nó chỉ định liệu danh sách sẽ được sắp xếp theo thứ tự tăng dần hay giảm dần. Nó nhận một giá trị Boolean, nghĩa là giá trị đó là True hoặc False. Giá trị mặc định là False , nghĩa là danh sách được sắp xếp theo thứ tự tăng dần. Đặt nó thành True sẽ sắp xếp danh sách ngược lại, theo thứ tự giảm dần.
  • key là tham số tùy chọn thứ hai. Nó có một hàm hoặc phương pháp được sử dụng để chỉ định bất kỳ tiêu chí sắp xếp chi tiết nào mà bạn có thể có.

Phương sort()thức trả về None, có nghĩa là không có giá trị trả về vì nó chỉ sửa đổi danh sách ban đầu. Nó không trả về một danh sách mới.

Cách sắp xếp các mục trong danh sách theo thứ tự tăng dần bằng phương pháp sort()

Như đã đề cập trước đó, theo mặc định, sort()sắp xếp các mục trong danh sách theo thứ tự tăng dần.

Thứ tự tăng dần (hoặc tăng dần) có nghĩa là các mặt hàng được sắp xếp từ giá trị thấp nhất đến cao nhất.

Giá trị thấp nhất ở bên trái và giá trị cao nhất ở bên phải.

Cú pháp chung để thực hiện việc này sẽ giống như sau:

list_name.sort()

Hãy xem ví dụ sau đây cho thấy cách sắp xếp danh sách các số nguyên:

# a list of numbers
my_numbers = [10, 8, 3, 22, 33, 7, 11, 100, 54]

#sort list in-place in ascending order
my_numbers.sort()

#print modified list
print(my_numbers)

#output

#[3, 7, 8, 10, 11, 22, 33, 54, 100]

Trong ví dụ trên, các số được sắp xếp từ nhỏ nhất đến lớn nhất.

Bạn cũng có thể đạt được điều tương tự khi làm việc với danh sách các chuỗi:

# a list of strings
programming_languages = ["Python", "Swift","Java", "C++", "Go", "Rust"]

#sort list in-place in alphabetical order
programming_languages.sort()

#print modified list
print(programming_languages)

#output

#['C++', 'Go', 'Java', 'Python', 'Rust', 'Swift']

Trong trường hợp này, mỗi chuỗi có trong danh sách được sắp xếp theo thứ tự không tuân theo.

Như bạn đã thấy trong cả hai ví dụ, danh sách ban đầu đã được thay đổi trực tiếp.

Cách sắp xếp các mục trong danh sách theo thứ tự giảm dần bằng phương pháp sort()

Thứ tự giảm dần (hoặc giảm dần) ngược lại với thứ tự tăng dần - các phần tử được sắp xếp từ giá trị cao nhất đến thấp nhất.

Để sắp xếp các mục trong danh sách theo thứ tự giảm dần, bạn cần sử dụng reverse tham số tùy chọn với phương thức sort() và đặt giá trị của nó thành True.

Cú pháp chung để thực hiện việc này sẽ giống như sau:

list_name.sort(reverse=True)

Hãy sử dụng lại cùng một ví dụ từ phần trước, nhưng lần này làm cho nó để các số được sắp xếp theo thứ tự ngược lại:

# a list of numbers
my_numbers = [10, 8, 3, 22, 33, 7, 11, 100, 54]

#sort list in-place in descending order
my_numbers.sort(reverse=True)

#print modified list
print(my_numbers)

#output

#[100, 54, 33, 22, 11, 10, 8, 7, 3]

Bây giờ tất cả các số được sắp xếp ngược lại, với giá trị lớn nhất ở bên tay trái và giá trị nhỏ nhất ở bên phải.

Bạn cũng có thể đạt được điều tương tự khi làm việc với danh sách các chuỗi.

# a list of strings
programming_languages = ["Python", "Swift","Java", "C++", "Go", "Rust"]

#sort list in-place in  reverse alphabetical order
programming_languages.sort(reverse=True)

#print modified list
print(programming_languages)

#output

#['Swift', 'Rust', 'Python', 'Java', 'Go', 'C++']

Các mục danh sách hiện được sắp xếp theo thứ tự bảng chữ cái ngược lại.

Cách sắp xếp các mục trong danh sách bằng cách sử dụng key tham số với phương thức sort()

Bạn có thể sử dụng key tham số để thực hiện các thao tác sắp xếp tùy chỉnh hơn.

Giá trị được gán cho key tham số cần phải là thứ có thể gọi được.

Callable là thứ có thể được gọi, có nghĩa là nó có thể được gọi và tham chiếu.

Một số ví dụ về các đối tượng có thể gọi là các phương thức và hàm.

Phương thức hoặc hàm được gán cho key này sẽ được áp dụng cho tất cả các phần tử trong danh sách trước khi bất kỳ quá trình sắp xếp nào xảy ra và sẽ chỉ định logic cho tiêu chí sắp xếp.

Giả sử bạn muốn sắp xếp danh sách các chuỗi dựa trên độ dài của chúng.

Đối với điều đó, bạn chỉ định len()hàm tích hợp cho key tham số.

Hàm len()sẽ đếm độ dài của từng phần tử được lưu trong danh sách bằng cách đếm các ký tự có trong phần tử đó.

programming_languages = ["Python", "Swift","Java", "C++", "Go", "Rust"]

programming_languages.sort(key=len)

print(programming_languages)

#output

#['Go', 'C++', 'Java', 'Rust', 'Swift', 'Python']

Trong ví dụ trên, các chuỗi được sắp xếp theo thứ tự tăng dần mặc định, nhưng lần này việc sắp xếp xảy ra dựa trên độ dài của chúng.

Chuỗi ngắn nhất ở bên trái và dài nhất ở bên phải.

Các keyreverse tham số cũng có thể được kết hợp.

Ví dụ: bạn có thể sắp xếp các mục trong danh sách dựa trên độ dài của chúng nhưng theo thứ tự giảm dần.

programming_languages = ["Python", "Swift","Java", "C++", "Go", "Rust"]

programming_languages.sort(key=len, reverse=True)

print(programming_languages)

#output

#['Python', 'Swift', 'Java', 'Rust', 'C++', 'Go']

Trong ví dụ trên, các chuỗi đi từ dài nhất đến ngắn nhất.

Một điều cần lưu ý nữa là bạn có thể tạo một chức năng sắp xếp tùy chỉnh của riêng mình, để tạo các tiêu chí sắp xếp rõ ràng hơn.

Ví dụ: bạn có thể tạo một hàm cụ thể và sau đó sắp xếp danh sách theo giá trị trả về của hàm đó.

Giả sử bạn có một danh sách các từ điển với các ngôn ngữ lập trình và năm mà mỗi ngôn ngữ lập trình được tạo ra.

programming_languages = [{'language':'Python','year':1991},
{'language':'Swift','year':2014},
{'language':'Java', 'year':1995},
{'language':'C++','year':1985},
{'language':'Go','year':2007},
{'language':'Rust','year':2010},
]

Bạn có thể xác định một hàm tùy chỉnh nhận giá trị của một khóa cụ thể từ từ điển.

💡 Hãy nhớ rằng khóa từ điển và key tham số sort()chấp nhận là hai thứ khác nhau!

Cụ thể, hàm sẽ lấy và trả về giá trị của year khóa trong danh sách từ điển, chỉ định năm mà mọi ngôn ngữ trong từ điển được tạo.

Giá trị trả về sau đó sẽ được áp dụng làm tiêu chí sắp xếp cho danh sách.

programming_languages = [{'language':'Python','year':1991},
{'language':'Swift','year':2014},
{'language':'Java', 'year':1995},
{'language':'C++','year':1985},
{'language':'Go','year':2007},
{'language':'Rust','year':2010},
]

def get_year(element):
    return element['year']

Sau đó, bạn có thể sắp xếp theo giá trị trả về của hàm bạn đã tạo trước đó bằng cách gán nó cho key tham số và sắp xếp theo thứ tự thời gian tăng dần mặc định:

programming_languages = [{'language':'Python','year':1991},
{'language':'Swift','year':2014},
{'language':'Java', 'year':1995},
{'language':'C++','year':1985},
{'language':'Go','year':2007},
{'language':'Rust','year':2010},
]

def get_year(element):
    return element['year']

programming_languages.sort(key=get_year)

print(programming_languages)

Đầu ra:

[{'language': 'C++', 'year': 1985}, {'language': 'Python', 'year': 1991}, {'language': 'Java', 'year': 1995}, {'language': 'Go', 'year': 2007}, {'language': 'Rust', 'year': 2010}, {'language': 'Swift', 'year': 2014}]

Nếu bạn muốn sắp xếp từ ngôn ngữ được tạo gần đây nhất đến ngôn ngữ cũ nhất hoặc theo thứ tự giảm dần, thì bạn sử dụng reverse=Truetham số:

programming_languages = [{'language':'Python','year':1991},
{'language':'Swift','year':2014},
{'language':'Java', 'year':1995},
{'language':'C++','year':1985},
{'language':'Go','year':2007},
{'language':'Rust','year':2010},
]

def get_year(element):
    return element['year']

programming_languages.sort(key=get_year, reverse=True)

print(programming_languages)

Đầu ra:

[{'language': 'Swift', 'year': 2014}, {'language': 'Rust', 'year': 2010}, {'language': 'Go', 'year': 2007}, {'language': 'Java', 'year': 1995}, {'language': 'Python', 'year': 1991}, {'language': 'C++', 'year': 1985}]

Để đạt được kết quả chính xác, bạn có thể tạo một hàm lambda.

Thay vì sử dụng hàm tùy chỉnh thông thường mà bạn đã xác định bằng def từ khóa, bạn có thể:

  • tạo một biểu thức ngắn gọn một dòng,
  • và không xác định tên hàm như bạn đã làm với def hàm. Các hàm lambda còn được gọi là các hàm ẩn danh .
programming_languages = [{'language':'Python','year':1991},
{'language':'Swift','year':2014},
{'language':'Java', 'year':1995},
{'language':'C++','year':1985},
{'language':'Go','year':2007},
{'language':'Rust','year':2010},
]

programming_languages.sort(key=lambda element: element['year'])

print(programming_languages)

Hàm lambda được chỉ định với dòng key=lambda element: element['year']sắp xếp các ngôn ngữ lập trình này từ cũ nhất đến mới nhất.

Sự khác biệt giữa sort()sorted()

Phương sort()thức hoạt động theo cách tương tự như sorted()hàm.

Cú pháp chung của sorted()hàm trông như sau:

sorted(list_name,reverse=...,key=...)

Hãy chia nhỏ nó:

  • sorted()là một hàm tích hợp chấp nhận một có thể lặp lại. Sau đó, nó sắp xếp nó theo thứ tự tăng dần hoặc giảm dần.
  • sorted()chấp nhận ba tham số. Một tham số là bắt buộc và hai tham số còn lại là tùy chọn.
  • list_name là tham số bắt buộc . Trong trường hợp này, tham số là danh sách, nhưng sorted()chấp nhận bất kỳ đối tượng có thể lặp lại nào khác.
  • sorted()cũng chấp nhận các tham số tùy chọn reversekey, đó là các tham số tùy chọn tương tự mà phương thức sort() chấp nhận.

Sự khác biệt chính giữa sort()sorted()sorted()hàm nhận một danh sách và trả về một bản sao được sắp xếp mới của nó.

Bản sao mới chứa các phần tử của danh sách ban đầu theo thứ tự được sắp xếp.

Các phần tử trong danh sách ban đầu không bị ảnh hưởng và không thay đổi.

Vì vậy, để tóm tắt sự khác biệt:

  • Phương sort()thức không có giá trị trả về và trực tiếp sửa đổi danh sách ban đầu, thay đổi thứ tự của các phần tử chứa trong nó.
  • Mặt khác, sorted()hàm có giá trị trả về, là một bản sao đã được sắp xếp của danh sách ban đầu. Bản sao đó chứa các mục danh sách của danh sách ban đầu theo thứ tự được sắp xếp. Cuối cùng, danh sách ban đầu vẫn còn nguyên vẹn.

Hãy xem ví dụ sau để xem nó hoạt động như thế nào:

#original list of numbers
my_numbers = [10, 8, 3, 22, 33, 7, 11, 100, 54]

#sort original list in default ascending order
my_numbers_sorted = sorted(my_numbers)

#print original list
print(my_numbers)

#print the copy of the original list that was created
print(my_numbers_sorted)

#output

#[10, 8, 3, 22, 33, 7, 11, 100, 54]
#[3, 7, 8, 10, 11, 22, 33, 54, 100]

Vì không có đối số bổ sung nào được cung cấp sorted(), nó đã sắp xếp bản sao của danh sách ban đầu theo thứ tự tăng dần mặc định, từ giá trị nhỏ nhất đến giá trị lớn nhất.

Và khi in danh sách ban đầu, bạn thấy rằng nó vẫn được giữ nguyên và các mục có thứ tự ban đầu.

Như bạn đã thấy trong ví dụ trên, bản sao của danh sách đã được gán cho một biến mới my_numbers_sorted,.

Một cái gì đó như vậy không thể được thực hiện với sort().

Hãy xem ví dụ sau để xem điều gì sẽ xảy ra nếu điều đó được thực hiện với phương thức sort().

my_numbers = [10, 8, 3, 22, 33, 7, 11, 100, 54]

my_numbers_sorted = my_numbers.sort()

print(my_numbers)
print(my_numbers_sorted)

#output

#[3, 7, 8, 10, 11, 22, 33, 54, 100]
#None

Bạn thấy rằng giá trị trả về của sort()None.

Cuối cùng, một điều khác cần lưu ý là các reversekey tham số mà sorted()hàm chấp nhận hoạt động giống hệt như cách chúng thực hiện với phương thức sort() bạn đã thấy trong các phần trước.

Khi nào sử dụng sort()sorted()

Dưới đây là một số điều bạn có thể muốn xem xét khi quyết định có nên sử dụng sort()vs. sorted()

Trước tiên, hãy xem xét loại dữ liệu bạn đang làm việc:

  • Nếu bạn đang làm việc nghiêm ngặt với một danh sách ngay từ đầu, thì bạn sẽ cần phải sử dụng sort()phương pháp này vì sort()chỉ được gọi trong danh sách.
  • Mặt khác, nếu bạn muốn linh hoạt hơn và chưa làm việc với danh sách, thì bạn có thể sử dụng sorted(). Hàm sorted()chấp nhận và sắp xếp mọi thứ có thể lặp lại (như từ điển, bộ giá trị và bộ) chứ không chỉ danh sách.

Tiếp theo, một điều khác cần xem xét là liệu bạn có giữ được thứ tự ban đầu của danh sách mà bạn đang làm việc hay không:

  • Khi gọi sort(), danh sách ban đầu sẽ bị thay đổi và mất thứ tự ban đầu. Bạn sẽ không thể truy xuất vị trí ban đầu của các phần tử danh sách. Sử dụng sort()khi bạn chắc chắn muốn thay đổi danh sách đang làm việc và chắc chắn rằng bạn không muốn giữ lại thứ tự đã có.
  • Mặt khác, sorted()nó hữu ích khi bạn muốn tạo một danh sách mới nhưng bạn vẫn muốn giữ lại danh sách bạn đang làm việc. Hàm sorted()sẽ tạo một danh sách được sắp xếp mới với các phần tử danh sách được sắp xếp theo thứ tự mong muốn.

Cuối cùng, một điều khác mà bạn có thể muốn xem xét khi làm việc với các tập dữ liệu lớn hơn, đó là hiệu quả về thời gian và bộ nhớ:

  • Phương sort()pháp này chiếm dụng và tiêu tốn ít bộ nhớ hơn vì nó chỉ sắp xếp danh sách tại chỗ và không tạo ra danh sách mới không cần thiết mà bạn không cần. Vì lý do tương tự, nó cũng nhanh hơn một chút vì nó không tạo ra một bản sao. Điều này có thể hữu ích khi bạn đang làm việc với danh sách lớn hơn chứa nhiều phần tử hơn.

Phần kết luận

Và bạn có nó rồi đấy! Bây giờ bạn đã biết cách sắp xếp một danh sách trong Python bằng sort()phương pháp này.

Bạn cũng đã xem xét sự khác biệt chính giữa sắp xếp danh sách bằng cách sử dụng sort()sorted().

Tôi hy vọng bạn thấy bài viết này hữu ích.

Để tìm hiểu thêm về ngôn ngữ lập trình Python, hãy xem Chứng chỉ Máy tính Khoa học với Python của freeCodeCamp .

Bạn sẽ bắt đầu từ những điều cơ bản và học theo cách tương tác và thân thiện với người mới bắt đầu. Bạn cũng sẽ xây dựng năm dự án vào cuối để áp dụng vào thực tế và giúp củng cố những gì bạn đã học được.

Nguồn: https://www.freecodecamp.org/news/python-sort-how-to-sort-a-list-in-python/

#python 

Khaitan

Khaitan

1635844603

पायथन में ट्रांसफॉर्मर के साथ संवादी एआई चैटबॉट

जानें कि पाइथन में प्री-ट्रेन्ड DialoGPT मॉडल के साथ संवादी प्रतिक्रियाएं उत्पन्न करने के लिए हगिंगफेस ट्रांसफॉर्मर लाइब्रेरी का उपयोग कैसे करें।

हाल के वर्षों में चैटबॉट्स ने बहुत लोकप्रियता हासिल की है, और जैसे-जैसे व्यवसाय के लिए चैटबॉट्स का उपयोग करने में रुचि बढ़ती है, शोधकर्ताओं ने संवादी एआई चैटबॉट्स को आगे बढ़ाने पर भी बहुत अच्छा काम किया है।

इस ट्यूटोरियल में, हम संवादी प्रतिक्रिया पीढ़ी के लिए पूर्व-प्रशिक्षित DialoGPT मॉडल को नियोजित करने के लिए हगिंगफेस ट्रांसफॉर्मर लाइब्रेरी का उपयोग करेंगे ।

DialoGPT एक बड़े पैमाने पर ट्यून करने योग्य तंत्रिका संवादी प्रतिक्रिया पीढ़ी मॉडल है जिसे रेडिट से निकाले गए 147M वार्तालापों पर प्रशिक्षित किया गया था, और अच्छी बात यह है कि आप स्क्रैच से प्रशिक्षण की तुलना में बेहतर प्रदर्शन प्राप्त करने के लिए इसे अपने डेटासेट के साथ ठीक कर सकते हैं।

आरंभ करने के लिए, आइए ट्रांसफॉर्मर स्थापित करें :

$ pip3 install transformers

एक नई पायथन फ़ाइल या नोटबुक खोलें और निम्न कार्य करें:

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

# model_name = "microsoft/DialoGPT-large"
model_name = "microsoft/DialoGPT-medium"
# model_name = "microsoft/DialoGPT-small"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)

DialoGPT के तीन संस्करण हैं; छोटा, मध्यम और बड़ा। बेशक, जितना बड़ा बेहतर होगा, लेकिन अगर आप इसे अपनी मशीन पर चला रहे हैं, तो मुझे लगता है कि छोटा या मध्यम आपकी याददाश्त को बिना किसी समस्या के फिट करता है। बड़े वाले को आज़माने के लिए आप Google Colab का भी उपयोग कर सकते हैं।

लालची खोज के साथ प्रतिक्रिया उत्पन्न करना

इस खंड में, हम प्रतिक्रिया उत्पन्न करने के लिए लालची खोज एल्गोरिथ्म का उपयोग करेंगे । यही है, हम चैटबॉट प्रतिक्रिया का चयन करते हैं जिसमें प्रत्येक समय चरण पर चुने जाने की सबसे अधिक संभावना होती है।

आइए लालची खोज का उपयोग करके हमारे AI के साथ चैट करने के लिए कोड बनाएं:

# chatting 5 times with greedy search
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        pad_token_id=tokenizer.eos_token_id,
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

आइए इस कोड के मूल की व्याख्या करें:

  • हम सबसे पहले चैटिंग के लिए यूजर से इनपुट लेते हैं।
  • हम input_idsDialoGPT टोकननाइज़र का उपयोग करने के लिए टेक्स्ट को एन्कोड करते हैं , हम स्ट्रिंग टोकन के अंत को भी जोड़ते हैं और इसे पाइटोरच टेंसर के रूप में वापस करते हैं।
  • अगर यह पहली बार बॉट के साथ चैट कर रहा है, तो हम input_idsएक पीढ़ी के लिए सीधे अपने मॉडल को फीड करते हैं। अन्यथा, हम torch.cat()मेथड की मदद से कॉन्सटेनेशन का उपयोग करके चैट हिस्ट्री को जोड़ देते हैं ।
  • उसके बाद, हम model.generate()चैटबॉट प्रतिक्रिया उत्पन्न करने के लिए विधि का उपयोग करते हैं ।
  • अंत में, जैसा कि लौटा हुआ आउटपुट एक टोकन अनुक्रम भी है, हम अनुक्रम का उपयोग करके डीकोड करते हैं tokenizer.decode()और यह सुनिश्चित skip_special_tokensकरने के Trueलिए सेट करते हैं कि हमें कोई कष्टप्रद विशेष टोकन जैसे कि <|endoftext|>. साथ ही, चूंकि मॉडल पूरे अनुक्रम को लौटाता है, हम पिछले चैट इतिहास को छोड़ देते हैं और केवल नए जेनरेट किए गए चैटबॉट उत्तर को प्रिंट करते हैं।

नीचे बॉट के साथ एक नमूना चर्चा है:

>> You:How can you be rich so quickly?
DialoGPT: I'm not rich, I'm just a rich man.
>> You:Ok, you don't make sense, how old are you ?
DialoGPT: I'm not a rich man, I'm just a rich man.
>> You:How can you be happy ?
DialoGPT: I'm not happy, I'm just a rich man.
>> You:But they say money buys happiness!
DialoGPT: Money buys happiness, but not happiness itself.
>> You:You don't make sense again!
DialoGPT: I'm not happy, I'm just a rich man.

आप देखते हैं कि मॉडल बहुत सारी प्रतिक्रियाओं को दोहराता है, क्योंकि ये सबसे अधिक संभावना है और यह हर बार इसे चुन रहा है।

डिफ़ॉल्ट रूप से, model.generate()लालची खोज एल्गोरिथ्म का उपयोग करता है जब कोई अन्य पैरामीटर सेट नहीं किया जाता है, अगले अनुभागों में, हम इस पद्धति में कुछ तर्क जोड़ेंगे कि क्या हम पीढ़ी में सुधार कर सकते हैं।

बीम खोज के साथ प्रतिक्रिया उत्पन्न करना

बीम खोज हमें num_beamsहर समय कदम पर परिकल्पना की सबसे अधिक संभावना रखते हुए उच्च संभावना अनुक्रमों के लापता होने के जोखिम को कम करने की अनुमति देता है और फिर उन अनुक्रमों को लेकर जिनकी समग्र उच्चतम संभावना है, नीचे दिए गए कोड बीम खोज के साथ चैटबॉट प्रतिक्रियाएं उत्पन्न करेंगे:

# chatting 5 times with beam search
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        num_beams=3,
        early_stopping=True,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

सेट करते समय num_beamsके लिए 3में model.generate()विधि है, तो हम हर बार कदम पर 3 शब्दों का चयन और अनुक्रम के उच्चतम समग्र संभावना खोजने के लिए उन्हें विकसित करने के लिए जा रहे हैं, की स्थापना num_beams1 के लिए लालची खोज के समान है।

नीचे बीम खोज का उपयोग करके चैटबॉट के साथ एक नमूना चर्चा है:

>> You:How can I be rich?
DialoGPT: You can't.
>> You:Why not?
DialoGPT: Because you can't.
>> You:Then how am I supposed to live well?
DialoGPT: You can't.
>> You:So basically, you want me to be a poor guy?
DialoGPT: No, I want you to be a rich guy.
>> You:Ok how to be rich, then?
DialoGPT: I don't know.

नमूनाकरण के साथ प्रतिक्रिया उत्पन्न करना

पिछले अनुभागों में, हमने उच्चतम संभाव्यता अनुक्रम उत्पन्न करने के लिए बीम और लालची खोज का उपयोग किया था। अब यह मशीनी अनुवाद या टेक्स्ट सारांश जैसे कार्यों के लिए बहुत अच्छा है जहां आउटपुट अनुमानित है। हालाँकि, चैटबॉट्स की तरह ओपन-एंडेड पीढ़ी के लिए यह सबसे अच्छा विकल्प नहीं है।

एक बेहतर पीढ़ी के लिए, हमें कुछ यादृच्छिकता पेश करने की आवश्यकता है जहां हम संभावनाओं के आधार पर उम्मीदवार अनुक्रमों की एक विस्तृत श्रृंखला से नमूना लेते हैं:

# chatting 5 times with sampling
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_k=0,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

इस बार, हमने नमूनाकरण के लिए सेट do_sampleकिया Trueहै, और हम यह इंगित करने के top_kलिए सेट हैं 0कि हम सभी संभावित संभावनाओं का चयन कर रहे हैं, हम बाद में top_kपैरामीटर पर चर्चा करेंगे ।

यहाँ इन मापदंडों के साथ बातचीत है:

>> You:Hello, how can I be rich?
DialoGPT: You can't
>> You:Really? then how others get rich?
DialoGPT: They work as money artists
>> You:How to be a money artist?
DialoGPT: I don't know, I don't have enough knowledge on artists
>> You:Alright, thank you!
DialoGPT: No problem, if you need tips pm me.
>> You:Great, you're my savior!
DialoGPT: Thank you for helping a stranger out like me!

स्पष्ट रूप से कुछ सुधार हैं। हालांकि, कम संभावनाओं वाले अनुक्रमों की एक विस्तृत सूची पर नमूना लेने से यादृच्छिक पीढ़ी हो सकती है (जैसा कि आप अंतिम वाक्य में देखते हैं)।

इसे और बेहतर बनाने के लिए, हम यह कर सकते हैं:

  • नमूनाकरण कम करें temperature, जिससे हमें कम संभावना वाले शब्दों को चुनने की संभावना कम करने में मदद मिलती है और उच्च संभावना वाले शब्दों को चुनने की संभावना बढ़ जाती है।
  • सभी संभावित घटनाओं को चुनने के बजाय टॉप-के नमूने का उपयोग करें, इससे हमें कम संभावना वाले शब्दों को चुनने से रोकने में मदद मिलेगी।
# chatting 5 times with Top K sampling & tweaking temperature
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_k=100,
        temperature=0.75,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

अब, हम संभाव्यता द्वारा अवरोही क्रम में शीर्ष शब्दों से नमूना लेने के लिए सेट top_kकरते हैं । हम उच्च संभावना वाले शब्दों को चुनने का एक उच्च मौका देने के लिए (डिफ़ॉल्ट है ) पर भी सेट करते हैं , तापमान को लालची खोज के समान ही सेट करते हैं, इसे अनंत पर सेट करना पूरी तरह से यादृच्छिक के समान है।100100temperature0.751.00.0

यहाँ इन मापदंडों के साथ एक चर्चा है:

>> You:How can I get rich?
DialoGPT: I'd also like to know this.
>> You:So you don't know it?
DialoGPT: I know it, but it doesn't matter.
>> You:Really? money matters, man!
DialoGPT: Well, money is money and I gotta get my money.
>> You:Yeah how to get them?
DialoGPT: Well, that's a question. I'd like to know more, just for curiosity's sake, to know what other people have said about how I should get rich.
>> You:Some robots like you told me you have to buy gold, silver or stocks.
DialoGPT: I think my wallet is empty.

जैसा कि आप देख सकते हैं, यह अब बहुत बेहतर है, बेझिझक ट्विक करें temperatureऔर top_kपैरामीटर देखें और देखें कि क्या यह इसमें सुधार कर सकता है।

न्यूक्लियस सैंपलिंग

न्यूक्लियस सैंपलिंग या टॉप-पी सैंपलिंग उन सबसे छोटे संभव शब्दों में से चुनता है जिनकी संचयी संभावना pहमारे द्वारा निर्धारित पैरामीटर से अधिक होती है ।

टॉप-पी सैंपलिंग का उपयोग करते हुए एक उदाहरण नीचे दिया गया है:

# chatting 5 times with nucleus sampling & tweaking temperature
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_p=0.95,
        top_k=0,
        temperature=0.75,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

हमने टॉप-के सैंपलिंग को अक्षम top_kकरने के 0लिए सेट किया है, लेकिन आप दोनों विधियों का उपयोग कर सकते हैं जो बेहतर काम करती हैं। यहाँ एक चैट है:

>> You:How can I be rich fast?
DialoGPT: Inflation and free money
>> You:lol, but that takes time, I need fast money.
DialoGPT: Your post makes no sense. You just need a lot of money to be rich fast
>> You:Ok how to get a lot of money?
DialoGPT: Buy gold and then trade it for money.
>> You:Hmm, I got your point, thanks.
DialoGPT: No problem. You have to have money to buy gold, but its only good for trading it.
>> You:Yeah, I understand, thank you so much.
DialoGPT: Ok, let me know if you need help

अब चैटबॉट कई मामलों में स्पष्ट रूप से समझ में आता है।

अब एक से अधिक चैटबॉट प्रतिक्रिया उत्पन्न करने के लिए कुछ कोड जोड़ते हैं, और फिर हम चुनते हैं कि अगले इनपुट में किस प्रतिक्रिया को शामिल करना है:

# chatting 5 times with nucleus & top-k sampling & tweaking temperature & multiple
# sentences
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids_list = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_p=0.95,
        top_k=50,
        temperature=0.75,
        num_return_sequences=5,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the outputs
    for i in range(len(chat_history_ids_list)):
      output = tokenizer.decode(chat_history_ids_list[i][bot_input_ids.shape[-1]:], skip_special_tokens=True)
      print(f"DialoGPT {i}: {output}")
    choice_index = int(input("Choose the response you want for the next input: "))
    chat_history_ids = torch.unsqueeze(chat_history_ids_list[choice_index], dim=0)

मैंने एक बार में 5 वाक्यों को वापस num_return_sequencesकरने के 5लिए निर्धारित किया है, हमें एक को चुनना होगा जिसे अगले अनुक्रम में शामिल किया जाएगा। यहां बताया गया है कि यह कैसे चला गया:

>> You:Hello, friend.
DialoGPT 0: Hey there!
DialoGPT 1: I am your friend, and I am also your friend.
DialoGPT 2: Hello. :
DialoGPT 3: Hiya! How are you?
DialoGPT 4: Hello. I like your username.
Choose the response you want for the next input: 3
>> You:Fine, thanks, what about you?
DialoGPT 0: Good. Not much to do.
DialoGPT 1: Not much, you?
DialoGPT 2: Fine, thanks.
DialoGPT 3: I'm okay, thank you for asking.
DialoGPT 4: I'm fine too.
Choose the response you want for the next input: 2
>> You:Can you tell me how can I get rich quickly?
DialoGPT 0: Yes, I can!
DialoGPT 1: Yes, just look up how to get rich on Google.
DialoGPT 2: Just keep doing your thing. You'll get rich.
DialoGPT 3: No, I can't.
DialoGPT 4: no, i have no money
Choose the response you want for the next input: 1
>> You:Yeah, but I thought you have an answer...
DialoGPT 0: I'm getting married in the morning.
DialoGPT 1: How do you get rich?
DialoGPT 2: I think there are many good answers, but I could send you one, if you want.
DialoGPT 3: I will, thanks!
DialoGPT 4: I thought you have an answer.
Choose the response you want for the next input: 2
>> You:Yes, please send me.
DialoGPT 0: You can send me link.
DialoGPT 1: I am very interested
DialoGPT 2: I sent you a PM
DialoGPT 3: I'll send you a PM
DialoGPT 4: I am always interested in new ideas.
Choose the response you want for the next input: 2

निष्कर्ष

और आप वहां जाएं, मुझे आशा है कि इस ट्यूटोरियल ने आपको DialoGPT और इसी तरह के मॉडल पर टेक्स्ट जेनरेट करने में मदद की। टेक्स्ट जेनरेट करने के तरीके के बारे में अधिक जानकारी के लिए, मैं आपको ट्रांसफॉर्मर्स गाइड के साथ टेक्स्ट जेनरेट करने का तरीका पढ़ने की अत्यधिक सलाह देता हूं ।

यह देखने के लिए कि क्या आप बॉट को बेहतर प्रदर्शन कर सकते हैं, मैं आपको मापदंडों को बदलना छोड़ दूँगा।

साथ ही, आप इसे टेक्स्ट-टू-स्पीच और स्पीच-टू-टेक्स्ट ट्यूटोरियल्स के साथ जोड़कर एक वर्चुअल असिस्टेंट जैसे एलेक्सा , सिरी , कोरटाना आदि बना सकते हैं।

#python #chatbot #ai 

Chatbot conversacional de IA con Transformers en Python

Aprenda a usar la biblioteca de transformadores Huggingface para generar respuestas conversacionales con el modelo DialoGPT previamente entrenado en Python.

Los chatbots han ganado mucha popularidad en los últimos años y, a medida que crece el interés en el uso de chatbots para empresas, los investigadores también hicieron un gran trabajo en el avance de los chatbots de IA conversacionales.

En este tutorial, usaremos la biblioteca de transformadores Huggingface para emplear el modelo DialoGPT previamente entrenado para la generación de respuestas conversacionales.

DialoGPT es un modelo de generación de respuesta conversacional neuronal sintonizable a gran escala que se entrenó en 147 millones de conversaciones extraídas de Reddit, y lo bueno es que puede ajustarlo con su conjunto de datos para lograr un mejor rendimiento que el entrenamiento desde cero.

Para comenzar, instalemos transformadores :

$ pip3 install transformers

Abra un nuevo archivo o cuaderno de Python y haga lo siguiente:

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

# model_name = "microsoft/DialoGPT-large"
model_name = "microsoft/DialoGPT-medium"
# model_name = "microsoft/DialoGPT-small"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)

Hay tres versiones de DialoGPT; pequeño, mediano y grande. Por supuesto, cuanto más grande, mejor, pero si ejecuta esto en su máquina, creo que el tamaño pequeño o mediano se adapta a su memoria sin problemas. También puede utilizar Google Colab para probar el más grande.

Generación de respuestas con búsqueda codiciosa

En esta sección, usaremos el algoritmo de búsqueda codiciosa para generar respuestas. Es decir, seleccionamos la respuesta del chatbot que tiene la mayor probabilidad de ser seleccionada en cada paso de tiempo.

Hagamos un código para chatear con nuestra IA usando una búsqueda codiciosa:

# chatting 5 times with greedy search
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        pad_token_id=tokenizer.eos_token_id,
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

Expliquemos el núcleo de este código:

  • Primero tomamos información del usuario para chatear.
  • Codificamos el texto para input_idsusar el tokenizador DialoGPT, también agregamos el final del token de cadena y lo devolvemos como un tensor de Pytorch.
  • Si esta es la primera vez que chateamos con el bot, alimentaremos directamente input_idsnuestro modelo durante una generación. De lo contrario, agregamos el historial de chat usando la concatenación con la ayuda del torch.cat()método.
  • Después de eso, usamos el model.generate()método para generar la respuesta del chatbot.
  • Por último, como la salida devuelta también es una secuencia tokenizada, decodificamos la secuencia usando tokenizer.decode()y configuramos skip_special_tokenspara Trueasegurarnos de que no veamos ningún token especial molesto como <|endoftext|>. Además, dado que el modelo devuelve la secuencia completa, omitimos el historial de chat anterior e imprimimos solo la respuesta del chatbot recién generada.

A continuación se muestra una discusión de muestra con el bot:

>> You:How can you be rich so quickly?
DialoGPT: I'm not rich, I'm just a rich man.
>> You:Ok, you don't make sense, how old are you ?
DialoGPT: I'm not a rich man, I'm just a rich man.
>> You:How can you be happy ?
DialoGPT: I'm not happy, I'm just a rich man.
>> You:But they say money buys happiness!
DialoGPT: Money buys happiness, but not happiness itself.
>> You:You don't make sense again!
DialoGPT: I'm not happy, I'm just a rich man.

Verá que el modelo repite muchas respuestas, ya que estas son la probabilidad más alta y lo elige cada vez.

De forma predeterminada, model.generate()utiliza un algoritmo de búsqueda codicioso cuando no se establecen otros parámetros; en las siguientes secciones, agregaremos algunos argumentos a este método para ver si podemos mejorar la generación.

Generación de respuestas con Beam Search

La búsqueda por haz nos permite reducir el riesgo de perder secuencias de alta probabilidad al mantener las num_beamshipótesis más probables en cada paso de tiempo y luego tomar las secuencias que tienen la probabilidad general más alta, el siguiente código generará respuestas de chatbot con búsqueda de haz:

# chatting 5 times with beam search
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        num_beams=3,
        early_stopping=True,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

Cuando se ajusta num_beamsa 3de model.generate()método, a continuación, vamos a seleccionar 3 palabras en cada paso de tiempo y desarrollarlas para encontrar la más alta probabilidad global de la secuencia, el establecimiento num_beamsde 1 es la misma que la búsqueda codiciosa.

A continuación se muestra una discusión de muestra con el chatbot usando la búsqueda de haz:

>> You:How can I be rich?
DialoGPT: You can't.
>> You:Why not?
DialoGPT: Because you can't.
>> You:Then how am I supposed to live well?
DialoGPT: You can't.
>> You:So basically, you want me to be a poor guy?
DialoGPT: No, I want you to be a rich guy.
>> You:Ok how to be rich, then?
DialoGPT: I don't know.

Generando respuestas con muestreo

En las secciones anteriores, usamos la búsqueda de rayos y codiciosos para generar la secuencia de probabilidad más alta. Eso es genial para tareas como la traducción automática o el resumen de texto donde el resultado es predecible. Sin embargo, no es la mejor opción para una generación abierta como en los chatbots.

Para una mejor generación, necesitamos introducir algo de aleatoriedad donde muestreamos de una amplia gama de secuencias candidatas basadas en probabilidades:

# chatting 5 times with sampling
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_k=0,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

Esta vez, establece do_sampleque Truepara el muestreo, y nos pusimos top_ka 0lo que indica que estamos seleccionando todas las probabilidades posibles, vamos a discutir más adelante top_kparámetro.

Aquí hay un chat con estos parámetros:

>> You:Hello, how can I be rich?
DialoGPT: You can't
>> You:Really? then how others get rich?
DialoGPT: They work as money artists
>> You:How to be a money artist?
DialoGPT: I don't know, I don't have enough knowledge on artists
>> You:Alright, thank you!
DialoGPT: No problem, if you need tips pm me.
>> You:Great, you're my savior!
DialoGPT: Thank you for helping a stranger out like me!

Claramente hay algunas mejoras. Sin embargo, el muestreo en una amplia lista de secuencias con bajas probabilidades puede conducir a una generación aleatoria (como se ve en la última oración).

Para mejorarlo aún más, podemos:

  • temperatureDisminuir el muestreo , eso nos ayuda a disminuir la probabilidad de elegir palabras de baja probabilidad y aumentar la probabilidad de elegir palabras de alta probabilidad.
  • Utilice el muestreo de Top-k en lugar de seleccionar todas las ocurrencias probables, esto nos ayudará a descartar palabras de baja probabilidad para que no sean seleccionadas.
# chatting 5 times with Top K sampling & tweaking temperature
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_k=100,
        temperature=0.75,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

Ahora, configuramos top_kpara 100muestrear las 100palabras principales ordenadas de forma descendente por probabilidad. También establecemos temperatureen 0.75(el valor predeterminado es 1.0) para brindar una mayor probabilidad de elegir palabras de alta probabilidad, establecer la temperatura en 0.0es lo mismo que la búsqueda codiciosa, establecerla en infinito es lo mismo que completamente aleatorio.

Aquí hay una discusión con estos parámetros:

>> You:How can I get rich?
DialoGPT: I'd also like to know this.
>> You:So you don't know it?
DialoGPT: I know it, but it doesn't matter.
>> You:Really? money matters, man!
DialoGPT: Well, money is money and I gotta get my money.
>> You:Yeah how to get them?
DialoGPT: Well, that's a question. I'd like to know more, just for curiosity's sake, to know what other people have said about how I should get rich.
>> You:Some robots like you told me you have to buy gold, silver or stocks.
DialoGPT: I think my wallet is empty.

Como se puede ver, es mucho mejor ahora, no dude en modificar temperaturey top_kparámetros y ver si puede mejorarlo.

Muestreo de núcleos

El muestreo de núcleo o muestreo de Top-p elige entre las palabras más pequeñas posibles cuya probabilidad acumulada excede el parámetro pque establecimos.

A continuación se muestra un ejemplo con el muestreo de Top-p:

# chatting 5 times with nucleus sampling & tweaking temperature
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_p=0.95,
        top_k=0,
        temperature=0.75,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

Configuramos top_kpara 0deshabilitar el muestreo de Top-k, pero puede usar ambos métodos, lo que tiende a funcionar mejor. Aquí hay un chat:

>> You:How can I be rich fast?
DialoGPT: Inflation and free money
>> You:lol, but that takes time, I need fast money.
DialoGPT: Your post makes no sense. You just need a lot of money to be rich fast
>> You:Ok how to get a lot of money?
DialoGPT: Buy gold and then trade it for money.
>> You:Hmm, I got your point, thanks.
DialoGPT: No problem. You have to have money to buy gold, but its only good for trading it.
>> You:Yeah, I understand, thank you so much.
DialoGPT: Ok, let me know if you need help

Ahora el chatbot claramente tiene sentido en muchos casos.

Ahora agreguemos algo de código para generar más de una respuesta de chatbot, y luego elegimos qué respuesta incluir en la siguiente entrada:

# chatting 5 times with nucleus & top-k sampling & tweaking temperature & multiple
# sentences
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids_list = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_p=0.95,
        top_k=50,
        temperature=0.75,
        num_return_sequences=5,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the outputs
    for i in range(len(chat_history_ids_list)):
      output = tokenizer.decode(chat_history_ids_list[i][bot_input_ids.shape[-1]:], skip_special_tokens=True)
      print(f"DialoGPT {i}: {output}")
    choice_index = int(input("Choose the response you want for the next input: "))
    chat_history_ids = torch.unsqueeze(chat_history_ids_list[choice_index], dim=0)

He configurado num_return_sequencespara 5devolver 5 oraciones a la vez, tenemos que elegir la que se incluirá en la siguiente secuencia. Así es como fue:

>> You:Hello, friend.
DialoGPT 0: Hey there!
DialoGPT 1: I am your friend, and I am also your friend.
DialoGPT 2: Hello. :
DialoGPT 3: Hiya! How are you?
DialoGPT 4: Hello. I like your username.
Choose the response you want for the next input: 3
>> You:Fine, thanks, what about you?
DialoGPT 0: Good. Not much to do.
DialoGPT 1: Not much, you?
DialoGPT 2: Fine, thanks.
DialoGPT 3: I'm okay, thank you for asking.
DialoGPT 4: I'm fine too.
Choose the response you want for the next input: 2
>> You:Can you tell me how can I get rich quickly?
DialoGPT 0: Yes, I can!
DialoGPT 1: Yes, just look up how to get rich on Google.
DialoGPT 2: Just keep doing your thing. You'll get rich.
DialoGPT 3: No, I can't.
DialoGPT 4: no, i have no money
Choose the response you want for the next input: 1
>> You:Yeah, but I thought you have an answer...
DialoGPT 0: I'm getting married in the morning.
DialoGPT 1: How do you get rich?
DialoGPT 2: I think there are many good answers, but I could send you one, if you want.
DialoGPT 3: I will, thanks!
DialoGPT 4: I thought you have an answer.
Choose the response you want for the next input: 2
>> You:Yes, please send me.
DialoGPT 0: You can send me link.
DialoGPT 1: I am very interested
DialoGPT 2: I sent you a PM
DialoGPT 3: I'll send you a PM
DialoGPT 4: I am always interested in new ideas.
Choose the response you want for the next input: 2

Conclusión

Y ahí lo tienes, espero que este tutorial te haya ayudado a generar texto en DialoGPT y modelos similares. Para obtener más información sobre cómo generar texto, le recomiendo que lea la guía Cómo generar texto con Transformers .

Te dejo ajustando los parámetros para ver si puedes hacer que el bot funcione mejor.

Además, puede combinar esto con tutoriales de texto a voz y de voz a texto para crear un asistente virtual como Alexa , Siri , Cortana , etc.

#python #chatbot #ai 

坂本  篤司

坂本 篤司

1633767300

Pythonのトランスフォーマーを備えた会話型AIチャットボット

チャットボットは近年多くの人気を博しており、ビジネスでのチャットボットの使用への関心が高まるにつれ、研究者は会話型AIチャットボットの進歩にも素晴らしい仕事をしました。

このチュートリアルでは、Huggingfaceトランスフォーマーライブラリを使用して、事前にトレーニングされたDialoGPTモデルを使用して会話型応答を生成します。

DialoGPTは、Redditから抽出された1億4700万の会話でトレーニングされた、大規模で調整可能なニューラル会話応答生成モデルです。データセットで微調整して、最初からトレーニングするよりも優れたパフォーマンスを実現できるのは良いことです。

開始するには、トランスフォーマーをインストールしましょう:

$ pip3 install transformers

新しいPythonファイルまたはノートブックを開き、次の手順を実行します。

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

# model_name = "microsoft/DialoGPT-large"
model_name = "microsoft/DialoGPT-medium"
# model_name = "microsoft/DialoGPT-small"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)

DialoGPTには3つのバージョンがあります。小、中、大。もちろん、大きいほど良いのですが、これをマシンで実行している場合は、中小規模でも問題なくメモリに収まると思います。また、GoogleColabを使用して大きなものを試すこともできます。

欲張り検索による応答の生成

このセクションでは、欲張り検索アルゴリズムを使用して応答を生成します。つまり、各タイムステップで選択される可能性が最も高いチャットボット応答を選択します。

欲張り検索を使用してAIとチャットするためのコードを作成しましょう:

# chatting 5 times with greedy search
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        pad_token_id=tokenizer.eos_token_id,
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

このコードのコアを説明しましょう:

  • まず、チャットのためにユーザーからの入力を受け取ります。
  • input_idsDialoGPTトークナイザーを使用してテキストをエンコードし、文字列トークンの末尾を追加して、Pytorchテンソルとして返します。
  • ボットとのチャットが初めての場合は、input_idsモデルに直接フィードして世代を超えます。それ以外の場合は、torch.cat()メソッドを使用して連結を使用してチャット履歴を追加します。
  • その後model.generate()、チャットボット応答を生成する方法を使用します。
  • 最後に、返される出力もトークン化されたシーケンスであるため、を使用tokenizer.decode()してシーケンスをデコードし、に設定skip_special_tokensTrueて、などの迷惑な特別なトークンが表示されないようにし<|endoftext|>ます。また、モデルはシーケンス全体を返すため、以前のチャット履歴をスキップし、新しく生成されたチャットボットの回答のみを出力します。

以下は、ボットとのディスカッションの例です。

>> You:How can you be rich so quickly?
DialoGPT: I'm not rich, I'm just a rich man.
>> You:Ok, you don't make sense, how old are you ?
DialoGPT: I'm not a rich man, I'm just a rich man.
>> You:How can you be happy ?
DialoGPT: I'm not happy, I'm just a rich man.
>> You:But they say money buys happiness!
DialoGPT: Money buys happiness, but not happiness itself.
>> You:You don't make sense again!
DialoGPT: I'm not happy, I'm just a rich man.

モデルは多くの応答を繰り返すことがわかります。これらは最も高い確率であり、毎回それを選択しているためです。

デフォルトでmodel.generate()は、他のパラメーターが設定されていない場合は欲張り検索アルゴリズムを使用します。次のセクションでは、このメソッドにいくつかの引数を追加して、生成を改善できるかどうかを確認します。

ビーム検索による応答の生成

ビーム検索でnum_beams、各タイムステップで最も可能性の高い仮説を保持し、全体的に最も確率の高いシーケンスを取得することで、高確率シーケンスを見逃すリスクを減らすことができます。以下のコードは、ビーム検索でチャットボット応答を生成します。

# chatting 5 times with beam search
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        num_beams=3,
        early_stopping=True,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

inメソッドに設定num_beamsする場合、各タイムステップで3つの単語を選択し、それらを開発して、シーケンスの全体的な確率が最も高くなるようにします。1に設定することは、欲張り検索と同じです。3model.generate()num_beams

以下は、ビーム検索を使用したチャットボットとのディスカッションの例です。

>> You:How can I be rich?
DialoGPT: You can't.
>> You:Why not?
DialoGPT: Because you can't.
>> You:Then how am I supposed to live well?
DialoGPT: You can't.
>> You:So basically, you want me to be a poor guy?
DialoGPT: No, I want you to be a rich guy.
>> You:Ok how to be rich, then?
DialoGPT: I don't know.

サンプリングによる応答の生成

前のセクションでは、ビーム検索と欲張り検索を使用して、最も確率の高いシーケンスを生成しました。これは、出力が予測可能な機械翻訳やテキスト要約などのタスクに最適です。ただし、チャットボットのように、オープンエンド世代には最適なオプションではありません。

より良い生成のために、確率に基づいて広範囲の候補配列からサンプリングするランダム性を導入する必要があります。

# chatting 5 times with sampling
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_k=0,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

今回は、サンプリング用に設定do_sampleTrue、可能なすべての確率を選択していることtop_k0示すように設定しましたtop_k。後でパラメーターについて説明します。

これらのパラメータを使用したチャットは次のとおりです。

>> You:Hello, how can I be rich?
DialoGPT: You can't
>> You:Really? then how others get rich?
DialoGPT: They work as money artists
>> You:How to be a money artist?
DialoGPT: I don't know, I don't have enough knowledge on artists
>> You:Alright, thank you!
DialoGPT: No problem, if you need tips pm me.
>> You:Great, you're my savior!
DialoGPT: Thank you for helping a stranger out like me!

明らかにいくつかの改善があります。ただし、確率の低いシーケンスの幅広いリストでサンプリングすると、ランダムに生成される可能性があります(最後の文で見られるように)。

それをさらに改善するために、次のことができます。

  • サンプリングをtemperature低くすると、確率の低い単語を選択する可能性が低くなり、確率の高い単語を選択する可能性が高くなります。
  • 発生する可能性のあるすべての単語を選択する代わりに、Top-kサンプリングを使用します。これにより、確率の低い単語が選択されないようにすることができます。
# chatting 5 times with Top K sampling & tweaking temperature
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_k=100,
        temperature=0.75,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

ここで、確率で降順にソートされた上位の単語からサンプリングtop_kする100ように設定しました100。またtemperature0.75(デフォルトは1.0)に設定して、確率の高い単語を選択する可能性を高めます。温度を0.0貪欲検索と同じに設定し、無限大に設定すると、完全にランダムと同じになります。

これらのパラメータについての説明は次のとおりです。

>> You:How can I get rich?
DialoGPT: I'd also like to know this.
>> You:So you don't know it?
DialoGPT: I know it, but it doesn't matter.
>> You:Really? money matters, man!
DialoGPT: Well, money is money and I gotta get my money.
>> You:Yeah how to get them?
DialoGPT: Well, that's a question. I'd like to know more, just for curiosity's sake, to know what other people have said about how I should get rich.
>> You:Some robots like you told me you have to buy gold, silver or stocks.
DialoGPT: I think my wallet is empty.

ご覧のとおり、今でははるかに優れています。パラメータを自由に調整してtemperaturetop_k改善できるかどうかを確認してください。

核サンプリング

核サンプリングまたはTop-pサンプリングは、累積確率がp設定したパラメーターを超える可能な限り小さい単語から選択します。

以下は、Top-pサンプリングを使用した例です。

# chatting 5 times with nucleus sampling & tweaking temperature
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_p=0.95,
        top_k=0,
        temperature=0.75,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the output
    output = tokenizer.decode(chat_history_ids[:, bot_input_ids.shape[-1]:][0], skip_special_tokens=True)
    print(f"DialoGPT: {output}")

Top-kサンプリングを無効にするtop_kよう0に設定しましたが、どちらの方法も使用できるため、より効果的に機能する傾向があります。これがチャットです:

>> You:How can I be rich fast?
DialoGPT: Inflation and free money
>> You:lol, but that takes time, I need fast money.
DialoGPT: Your post makes no sense. You just need a lot of money to be rich fast
>> You:Ok how to get a lot of money?
DialoGPT: Buy gold and then trade it for money.
>> You:Hmm, I got your point, thanks.
DialoGPT: No problem. You have to have money to buy gold, but its only good for trading it.
>> You:Yeah, I understand, thank you so much.
DialoGPT: Ok, let me know if you need help

現在、チャットボットは多くの場合明らかに意味があります。

次に、複数のチャットボット応答を生成するコードを追加して、次の入力に含める応答を選択します。

# chatting 5 times with nucleus & top-k sampling & tweaking temperature & multiple
# sentences
for step in range(5):
    # take user input
    text = input(">> You:")
    # encode the input and add end of string token
    input_ids = tokenizer.encode(text + tokenizer.eos_token, return_tensors="pt")
    # concatenate new user input with chat history (if there is)
    bot_input_ids = torch.cat([chat_history_ids, input_ids], dim=-1) if step > 0 else input_ids
    # generate a bot response
    chat_history_ids_list = model.generate(
        bot_input_ids,
        max_length=1000,
        do_sample=True,
        top_p=0.95,
        top_k=50,
        temperature=0.75,
        num_return_sequences=5,
        pad_token_id=tokenizer.eos_token_id
    )
    #print the outputs
    for i in range(len(chat_history_ids_list)):
      output = tokenizer.decode(chat_history_ids_list[i][bot_input_ids.shape[-1]:], skip_special_tokens=True)
      print(f"DialoGPT {i}: {output}")
    choice_index = int(input("Choose the response you want for the next input: "))
    chat_history_ids = torch.unsqueeze(chat_history_ids_list[choice_index], dim=0)

一度に5つの文を返すように設定num_return_sequences5ました。次のシーケンスに含まれる文を選択する必要があります。これがどのように進んだかです:

>> You:Hello, friend.
DialoGPT 0: Hey there!
DialoGPT 1: I am your friend, and I am also your friend.
DialoGPT 2: Hello. :
DialoGPT 3: Hiya! How are you?
DialoGPT 4: Hello. I like your username.
Choose the response you want for the next input: 3
>> You:Fine, thanks, what about you?
DialoGPT 0: Good. Not much to do.
DialoGPT 1: Not much, you?
DialoGPT 2: Fine, thanks.
DialoGPT 3: I'm okay, thank you for asking.
DialoGPT 4: I'm fine too.
Choose the response you want for the next input: 2
>> You:Can you tell me how can I get rich quickly?
DialoGPT 0: Yes, I can!
DialoGPT 1: Yes, just look up how to get rich on Google.
DialoGPT 2: Just keep doing your thing. You'll get rich.
DialoGPT 3: No, I can't.
DialoGPT 4: no, i have no money
Choose the response you want for the next input: 1
>> You:Yeah, but I thought you have an answer...
DialoGPT 0: I'm getting married in the morning.
DialoGPT 1: How do you get rich?
DialoGPT 2: I think there are many good answers, but I could send you one, if you want.
DialoGPT 3: I will, thanks!
DialoGPT 4: I thought you have an answer.
Choose the response you want for the next input: 2
>> You:Yes, please send me.
DialoGPT 0: You can send me link.
DialoGPT 1: I am very interested
DialoGPT 2: I sent you a PM
DialoGPT 3: I'll send you a PM
DialoGPT 4: I am always interested in new ideas.
Choose the response you want for the next input: 2

結論

このチュートリアルが、DialoGPTおよび同様のモデルでテキストを生成する方法に役立つことを願っています。テキストを生成する方法の詳細については、「Transformersを使用してテキストを生成する方法」ガイドを読むことを強くお勧めします。

ボットのパフォーマンスを向上させることができるかどうかを確認するために、パラメーターを微調整しておきます。

また、これをテキスト読み上げおよび音声読み上げのチュートリアルと組み合わせて、AlexaSiriCortanaなどの仮想アシスタントを構築することもできます

リンク: https://www.thepythoncode.com/article/conversational-ai-chatbot-with-huggingface-transformers-in-python

#python