活动介绍

对数据库name相同的分数相加起来

时间: 2023-06-07 09:10:44 浏览: 74
您好!感谢使用ChitGPT进行对话。 针对您的问题,如果您想对数据库中某个name相同的数值进行求和,可以使用SQL语句中的聚合函数SUM来实现。例如: SELECT name, SUM(score) FROM table_name GROUP BY name; 这条SQL语句可以将表格table_name中所有name相同的score数值相加并进行分组,最终返回每个name和对应的分数之和。 希望这个回答能够帮到您,如果您有其他问题,请继续问我。
相关问题

数据库实验四 运算符

### 关于数据库实验中运算符的使用 在进行数据库操作时,了解并掌握各种运算符对于编写高效且准确的 SQL 查询至关重要。以下是有关 MySQL 中常用运算符及其应用实例。 #### 1. 算术运算符 算术运算符用于执行基本数学计算,在 SELECT 命令中可以用来处理数值字段的数据。 - 加法 (+): 将两个表达式的值相加[^1] - 减法 (-): 计算两数之差[^1] - 乘法 (*): 返回两数相乘的结果[^1] - 除法 (/): 对两个数字做除法运算 ```sql SELECT price * quantity AS total_cost FROM orders; ``` 此查询语句会返回订单表 `orders` 中每条记录的价格 (`price`) 和数量 (`quantity`) 的乘积作为总成本(`total_cost`)。 #### 2. 比较运算符 比较运算符允许用户设定条件来筛选符合条件的数据行。 - 等于 (=): 判断左侧与右侧是否相同 - 不等于 (!= 或 <>): 测试两侧不匹配的情况 - 大于 (>): 验证左边大于右边的关系 - 小于 (<): 检查左方小于右方的情形 - 大于等于 (>=): 左侧大于或等于右侧时成立 - 小于等于 (<=): 右边不低于左边则为真 ```sql SELECT student_name, grade FROM students WHERE grade >= 90; ``` 上述代码片段展示了如何通过成绩(`grade`)高于或等于特定阈值(这里是90分)来获取学生姓名(`student_name`)列表。 #### 3. 逻辑运算符 逻辑运算符帮助组合多个布尔表达式以创建更复杂的查询条件。 - AND: 当所有给定条件均为真的情况下才返回 TRUE - OR: 如果任意一个条件满足即视为整体为真 - NOT: 否定某个条件的效果,即将原结果反转 ```sql SELECT course_title FROM courses WHERE department = 'Computer Science' AND credits > 3; ``` 这段脚本说明了怎样找出计算机科学系开设且学分数超过三个单位的所有课程名称(`course_title`)。 #### 4. 字符串模式匹配运算符 这些特殊类型的运算符专用于字符串搜索和过滤目的。 - LIKE: 支持通配符 %(代表零个到多个字符)和 _ (表示单个字符),可用于模糊查找 ```sql SELECT book_title FROM books WHERE title LIKE '%SQL%'; ``` 该例子演示了寻找书名中含有 "SQL" 子串的所有书籍标题(`book_title`)的方法。 为了确保正确地运用以上提到的各种运算符,请务必先确认当前工作环境已切换至目标数据库[^2]。这一步骤非常重要,因为如果未指定正确的数据库,则可能会遇到诸如“无效列名”或“无效对象名”的错误提示信息。

10-10 计算Product表中销售价格和进货价格的合计值 分数 10 作者 冰冰 单位 广东东软学院 要求编写SQL语句,查询Product表中销售价格和进货价格的合计值。 表结构: CREATE TABLE Product (product_id CHAR(4) NOT NULL, --商品编号 product_name VARCHAR(100) NOT NULL, --商品名称 product_type VARCHAR(32) NOT NULL, --商品种类 sale_price INTEGER , --销售价格 purchase_price INTEGER , --进货价格 regist_date DATE , --登记日期 PRIMARY KEY (product_id)); 表样例 Product表 图1.png 输出样例: Product表 图2.png 代码长度限制 16 KB 时间限制 400 ms 数据库 SQL Server 结果输出要求 忽略顺序只对比数据 建表语句 结果表结构

<think>好的,我现在需要帮助用户解决如何用SQL计算Product表中sale_price和purchase_price字段的合计值,目标数据库是SQL Server。首先,我得确认用户的需求是什么。他们想得到这两个字段的总和,可能是每个字段各自的总和,或者是每行两个字段相加的总和?不过根据问题描述中的“合计值”,通常是指整个表中这两个字段各自的总和,比如sale_price的总和和purchase_price的总和。 接下来,我需要回忆SQL中求和的基本语法。通常,使用SUM()函数来计算某列的总和。如果是求每个列的合计,应该分别对sale_price和purchase_price使用SUM函数。例如: SELECT SUM(sale_price) AS total_sale, SUM(purchase_price) AS total_purchase FROM Product; 但需要确认用户是否需要这两个列各自的总和,还是每行中这两个字段的和相加。比如,每一行的sale_price加上purchase_price,然后显示每一行的结果,或者是所有行的总和。不过用户的问题中提到“合计值”,更可能是指整个表的总和,所以应该是前者的情况。 另外,用户提供的参考引用中有一个CREATE TABLE的示例,里面有sale_price和purchase_price字段,都是INTEGER类型。所以这两个字段应该是数值类型,可以进行SUM操作。需要注意的是,如果这两个字段中有NULL值,SUM函数会忽略NULL。但根据表结构,sale_price有DEFAULT 0,而purchase_price没有默认值,可能允许NULL。因此,在求和时可能需要处理NULL的情况,比如使用COALESCE将NULL转换为0。例如: SELECT SUM(COALESCE(sale_price, 0)) AS total_sale, SUM(COALESCE(purchase_price, 0)) AS total_purchase FROM Product; 但用户的问题中可能假设这些字段没有NULL值,所以可能不需要处理。但为了稳妥,可能需要在回答中提到这一点。 然后,目标数据库是SQL Server,所以语法上应该符合T-SQL的要求。不过基本的SUM函数在SQL Server中是支持的,所以不需要特别的调整。 总结,正确的SQL语句应该是SELECT SUM(sale_price)和SUM(purchase_price)的组合,并使用别名让结果更易读。同时,需要指出可能的NULL值处理,以增强答案的健壮性。因此,最终的答案应该包含这两个SUM函数,并解释如何处理NULL的情况。</think>要计算SQL Server中Product表$sale\_price$和$purchase\_price$字段的合计值,可以使用聚合函数$SUM()$配合$SELECT$语句实现。具体操作步骤如下: ### 方法一:分别计算两列总和 ```sql SELECT SUM(sale_price) AS total_sale, SUM(purchase_price) AS total_purchase FROM Product; ``` - $SUM()$函数自动忽略NULL值 - $AS$关键字为计算结果命名列标题 - 结果返回两列:销售总额和进货总额 ### 方法二:处理空值计算 若字段存在NULL值,推荐使用$ISNULL()$函数处理: ```sql SELECT SUM(ISNULL(sale_price, 0)) AS safe_total_sale, SUM(ISNULL(purchase_price, 0)) AS safe_total_purchase FROM Product; ``` - 将NULL转换为0参与计算 - 避免因空值导致合计结果偏差 ### 执行验证 ```sql -- 示例数据验证 SELECT * FROM Product WHERE product_id IN ('0001','0002'); ``` 执行结果示例: | total_sale | total_purchase | |------------|----------------| | 2500 | 1800 | [^1]: 表结构定义参考示例中的`productins`表结构,包含$sale\_price$和$purchase\_price$字段。
阅读全文

相关推荐

import os import re import math import http.server import socketserver import urllib.parse from collections import defaultdict from lxml import etree, html # 配置信息 PORT = 8000 DOCUMENTS_DIR = "documents" # 存放HTML文件的目录 INDEX_FILE = "search_index.json" # 创建文档目录(如果不存在) os.makedirs(DOCUMENTS_DIR, exist_ok=True) # 示例文档(实际应用中会从文件系统加载) sample_docs = [ { "id": 1, "title": "Python编程语言", "content": "Python是一种高级编程语言,由Guido van Rossum创建。它强调代码可读性和简洁的语法。", "url": "doc1.html" }, { "id": 2, "title": "lxml库简介", "content": "lxml是Python中处理XML和HTML的强大库,基于libxml2和libxslt库构建。", "url": "doc2.html" }, { "id": 3, "title": "构建搜索网站", "content": "使用Python和lxml可以构建高效的搜索系统,解析HTML并提取关键信息。", "url": "doc3.html" } ] # 创建示例文档 for doc in sample_docs: with open(os.path.join(DOCUMENTS_DIR, doc["url"]), "w", encoding="utf-8") as f: f.write(f""" <!DOCTYPE html> <html> <head> <title>{doc['title']}</title> </head> <body> {doc['title']} {doc['content']} 相关主题: Python, 编程, lxml, 搜索系统 </body> </html> """) class SearchEngine: def __init__(self): self.index = defaultdict(dict) # 倒排索引 {词: {文档ID: 词频}} self.documents = {} # 文档元数据 {文档ID: {标题, url, content}} self.doc_count = 0 self.doc_lengths = {} # 文档长度(词数) def tokenize(self, text): """简单的分词函数""" words = re.findall(r'\b\w+\b', text.lower()) return words def build_index(self, documents_dir): """构建搜索索引""" self.index.clear() self.documents.clear() self.doc_count = 0 # 遍历文档目录中的所有HTML文件 for filename in os.listdir(documents_dir): if filename.endswith(".html"): doc_id = self.doc_count + 1 self.doc_count += 1 filepath = os.path.join(documents_dir, filename) # 使用lxml解析HTML with open(filepath, "r", encoding="utf-8") as f: content = f.read() tree = html.fromstring(content) # 提取文档内容 title = tree.findtext(".//title") or filename body_text = " ".join(tree.xpath("//body//text()")) # 存储文档元数据 self.documents[doc_id] = { "title": title.strip(), "url": filename, "content": body_text.strip()[:200] + "..." # 摘要 } # 分词并更新索引 words = self.tokenize(title + " " + body_text) self.doc_lengths[doc_id] = len(words) # 更新倒排索引 for word in set(words): # 使用set避免重复计数 if doc_id not in self.index[word]: self.index[word][doc_id] = 0 self.index[word][doc_id] += words.count(word) def tf_idf(self, term, doc_id): """计算TF-IDF分数""" # 词频(TF) tf = self.index[term].get(doc_id, 0) / self.doc_lengths[doc_id] # 逆文档频率(IDF) idf = math.log(self.doc_count / (1 + len(self.index[term]))) return tf * idf def search(self, query): """执行搜索查询""" if not self.index: self.build_index(DOCUMENTS_DIR) query_terms = self.tokenize(query) scores = defaultdict(float) # 计算每个文档的相关性分数 for term in query_terms: if term in self.index: for doc_id in self.index[term]: score = self.tf_idf(term, doc_id) scores[doc_id] += score # 按分数排序 sorted_results = sorted(scores.items(), key=lambda x: x[1], reverse=True) # 准备结果 results = [] for doc_id, score in sorted_results: if score > 0: # 只返回有相关性的文档 doc_info = self.documents[doc_id].copy() doc_info["score"] = round(score, 4) results.append(doc_info) return results # 创建搜索引擎实例 search_engine = SearchEngine() class SearchHandler(http.server.SimpleHTTPRequestHandler): def do_GET(self): """处理GET请求""" if self.path == "/": # 显示搜索页面 self.send_response(200) self.send_header("Content-type", "text/html; charset=utf-8") self.end_headers() html_content = self.generate_search_page() self.wfile.write(html_content.encode("utf-8")) elif self.path.startswith("/search?"): # 处理搜索请求 query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query).get("q", [""])[0] self.send_response(200) self.send_header("Content-type", "text/html; charset=utf-8") self.end_headers() results = search_engine.search(query) html_content = self.generate_results_page(query, results) self.wfile.write(html_content.encode("utf-8")) else: # 处理静态文件请求 super().do_GET() def generate_search_page(self): """生成搜索页面""" return f""" <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Python搜索网站</title> <style> body {{ font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; }} .container {{ max-width: 800px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }} h1 {{ color: #2c3e50; text-align: center; }} .search-box {{ display: flex; margin: 20px 0; }} input[type="text"] {{ flex: 1; padding: 12px; font-size: 16px; border: 1px solid #ddd; border-radius: 4px 0 0 4px; }} button {{ padding: 12px 20px; background: #3498db; color: white; border: none; border-radius: 0 4px 4px 0; cursor: pointer; font-size: 16px; }} button:hover {{ background: #2980b9; }} .result-item {{ margin: 15px 0; padding: 15px; border: 1px solid #eee; border-radius: 4px; }} .result-title {{ font-size: 18px; font-weight: bold; margin-bottom: 5px; color: #3498db; }} .result-url {{ color: #006621; font-size: 14px; margin-bottom: 5px; }} .result-snippet {{ color: #545454; }} .no-results {{ text-align: center; padding: 20px; color: #777; }} .footer {{ margin-top: 30px; text-align: center; color: #777; font-size: 14px; }} </style> </head> <body> Python搜索网站 <form action="/https/wenku.csdn.net/search" method="get"> <input type="text" name="q" placeholder="输入搜索关键词..."> <button type="submit">搜索</button> </form> 这个搜索网站使用Python内置库和lxml构建,可以索引和搜索本地HTML文档。 示例文档已包含在系统中,尝试搜索: "Python", "lxml", "搜索"等关键词。 使用Python + lxml构建 | 本地搜索系统 </body> </html> """ def generate_results_page(self, query, results): """生成搜索结果页面""" results_html = "" if results: for result in results: results_html += f""" {result['title']} /{DOCUMENTS_DIR}/{result['url']} {result['content']} 相关性: {result['score']} """ else: results_html = '没有找到相关结果' return f""" <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>搜索: {query} - Python搜索网站</title> <style> body {{ font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; }} .container {{ max-width: 800px; margin: 0 auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }} h1 {{ color: #2c3e50; }} .search-box {{ display: flex; margin: 20px 0; }} input[type="text"] {{ flex: 1; padding: 12px; font-size: 16px; border: 1px solid #ddd; border-radius: 4px 0 0 4px; }} button {{ padding: 12px 20px; background: #3498db; color: white; border: none; border-radius: 0 4px 4px 0; cursor: pointer; font-size: 16px; }} button:hover {{ background: #2980b9; }} .results-count {{ color: #777; margin-bottom: 20px; }} .result-item {{ margin: 15px 0; padding: 15px; border: 1px solid #eee; border-radius: 4px; }} .result-title {{ font-size: 18px; font-weight: bold; margin-bottom: 5px; color: #3498db; }} .result-url {{ color: #006621; font-size: 14px; margin-bottom: 5px; }} .result-snippet {{ color: #545454; }} .result-info {{ color: #777; font-size: 14px; margin-top: 5px; }} .no-results {{ text-align: center; padding: 20px; color: #777; }} </style> </head> <body> Python搜索网站 <form action="/https/wenku.csdn.net/search" method="get"> <input type="text" name="q" value="{query}"> <button type="submit">搜索</button> </form> 找到 {len(results)} 条结果 {results_html} 返回首页 | 使用Python + lxml构建 </body> </html> """ # 启动服务器 with socketserver.TCPServer(("", PORT), SearchHandler) as httpd: print(f"服务器运行在端口 {PORT}") print(f"访问地址: http://localhost:{PORT}/") print("按Ctrl+C停止服务器") try: httpd.serve_forever() except KeyboardInterrupt: print("\n服务器已停止")让浏览器成为专业AI工具,无需字典列表元组集合,还有网络请求,无需外部库,加上后的完整代码

import os import re import time import torch import torch.nn as nn import torch.optim as optim import pandas as pd import numpy as np import joblib # 添加缺失的导入 from datetime import datetime from torch.utils.data import Dataset, DataLoader, random_split from tqdm import tqdm import pickle import mysql.connector from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.metrics.pairwise import cosine_similarity from gensim.models import Word2Vec import spacy nlp = spacy.load("en_core_web_sm", disable=["parser", "ner"]) STOPWORDS = spacy.lang.en.stop_words.STOP_WORDS def clean_text(text): return re.sub(r'[^a-zA-Z0-9\s]', '', str(text)).strip().lower() def tokenize(text): """优化tokenize函数,移除冗余检查""" doc = nlp(clean_text(text)) return [token.text for token in doc if token.text not in STOPWORDS] # 移除isalnum检查 def preprocess(text): tokens = tokenize(text) return " ".join(tokens) class SemanticMatchModel(nn.Module): def __init__(self, input_dim): super().__init__() self.fc1 = nn.Linear(input_dim, 256) self.bn1 = nn.BatchNorm1d(256) self.fc2 = nn.Linear(256, 128) self.bn2 = nn.BatchNorm1d(128) self.fc3 = nn.Linear(128, 64) self.bn3 = nn.BatchNorm1d(64) self.fc4 = nn.Linear(64, 1) self.dropout = nn.Dropout(0.3) self.relu = nn.ReLU() self.sigmoid = nn.Sigmoid() def forward(self, x): x = self.relu(self.bn1(self.fc1(x))) x = self.dropout(x) x = self.relu(self.bn2(self.fc2(x))) x = self.dropout(x) x = self.relu(self.bn3(self.fc3(x))) x = self.dropout(x) x = self.sigmoid(self.fc4(x)) return x class QADataset(Dataset): def __init__(self, qa_pairs, tfidf_vectorizer, negative_ratio=1.0): self.qa_pairs = qa_pairs self.vectorizer = tfidf_vectorizer self.samples = [] # 构建正样本 for i, (q, a) in enumerate(self.qa_pairs): self.samples.append((q, a, 1)) # 优化负样本构建逻辑 if negative_ratio > 0: total_pairs = len(self.qa_pairs) all_answers = [a for _, a in self.qa_pairs] # 预先生成负样本索引 neg_indices = np.random.choice( len(all_answers), size=int(total_pairs * negative_ratio), replace=True ) for idx, (q, a) in enumerate(self.qa_pairs): sample_count = int(negative_ratio) start = idx * sample_count end = start + sample_count for j in range(start, end): if j < len(neg_indices): neg_a = all_answers[neg_indices[j]] # 确保不是当前答案 if neg_a != a: self.samples.append((q, neg_a, 0)) def __len__(self): return len(self.samples) def __getitem__(self, idx): q, a, label = self.samples[idx] q_vec = self.vectorizer.transform([preprocess(q)]).toarray()[0] a_vec = self.vectorizer.transform([preprocess(a)]).toarray()[0] pair_vec = np.concatenate((q_vec, a_vec)) return torch.tensor(pair_vec, dtype=torch.float32), torch.tensor(label, dtype=torch.float32) class KnowledgeBase: def __init__(self, host='localhost', user='root', password='hy188747', database='ubuntu_qa', table='qa_pair', model_dir=r"D:\NLP-PT\PT4\model", negative_ratio=1.0): print("🔄 初始化知识库...") self.host = host self.user = user self.password = password self.database = database self.table = table self.model_dir = model_dir self.negative_ratio = negative_ratio os.makedirs(self.model_dir, exist_ok=True) self.qa_pairs = [] self.q_texts = [] self.a_texts = [] self.semantic_model = None self.word2vec_model = None self.tfidf_vectorizer = None self.tfidf_matrix = None # 调整初始化顺序 self.load_data_from_mysql() self.load_or_cache_processed_questions() self.load_cached_tfidf() self.load_cached_word2vec_model() # 最后加载模型(确保依赖项已初始化) model_path = os.path.join(self.model_dir, 'semantic_match_model.pth') if os.path.exists(model_path): self.load_model() else: print("⚠ 语义匹配模型未训练,请先训练模型。") def load_data_from_mysql(self): print("🔄 正在连接 MySQL,加载问答数据...") try: conn = mysql.connector.connect( host=self.host, user=self.user, password=self.password, database=self.database ) cursor = conn.cursor() query = f"SELECT question_text, answer_text FROM {self.table}" cursor.execute(query) rows = cursor.fetchall() self.qa_pairs = [(row[0], row[1]) for row in rows] self.q_texts = [pair[0] for pair in self.qa_pairs] self.a_texts = [pair[1] for pair in self.qa_pairs] print(f"✅ 成功从 MySQL 加载 {len(self.qa_pairs)} 条问答数据。") except Exception as e: print(f"❌ 数据库连接失败: {e}") self.qa_pairs = [] finally: if conn.is_connected(): conn.close() def load_or_cache_processed_questions(self): cache_path = os.path.join(self.model_dir, 'processed_questions.pkl') if os.path.exists(cache_path): print("🔄 使用缓存预处理后的分词文本。") with open(cache_path, 'rb') as f: self.processed_q_list = pickle.load(f) else: print("🔄 正在预处理问题文本(首次较慢)...") self.processed_q_list = [preprocess(q) for q in tqdm(self.q_texts)] with open(cache_path, 'wb') as f: pickle.dump(self.processed_q_list, f) print("✅ 预处理缓存已保存。") def load_cached_tfidf(self): cache_tfidf_matrix = os.path.join(self.model_dir, 'tfidf_matrix.npz') cache_qa_list = os.path.join(self.model_dir, 'tfidf_qa.pkl') tfidf_path = os.path.join(self.model_dir, 'tfidf_vectorizer.pkl') if os.path.exists(tfidf_path) and os.path.exists(cache_tfidf_matrix) and os.path.exists(cache_qa_list): print("🔄 加载 TF-IDF 缓存版本。") self.tfidf_vectorizer = joblib.load(tfidf_path) self.tfidf_matrix = np.load(cache_tfidf_matrix)['tfidf'] with open(cache_qa_list, 'rb') as f: self.tfidf_qa = pickle.load(f) else: print("🔄 创建并构建 TF-IDF(首次较慢)...") self.tfidf_vectorizer = TfidfVectorizer( tokenizer=lambda x: x.split(), lowercase=False, max_features=10000 ) self.tfidf_qa = self.processed_q_list self.tfidf_matrix = self.tfidf_vectorizer.fit_transform(self.tfidf_qa).toarray() print("✅ TF-IDF 构建完成。") joblib.dump(self.tfidf_vectorizer, tfidf_path) np.savez_compressed(cache_tfidf_matrix, tfidf=self.tfidf_matrix) with open(cache_qa_list, 'wb') as f: pickle.dump(self.tfidf_qa, f) def load_cached_word2vec_model(self): word2vec_path = os.path.join(self.model_dir, 'word2vec.model') if os.path.exists(word2vec_path): print("🔄 加载缓存中的 Word2Vec 模型...") self.word2vec_model = Word2Vec.load(word2vec_path) else: print("🔄 训练 Word2Vec 模型(首次较慢)...") tokenized_questions = [preprocess(q).split() for q in self.q_texts] self.word2vec_model = Word2Vec( sentences=tokenized_questions, vector_size=100, window=5, min_count=1, workers=4, epochs=10 ) self.word2vec_model.save(word2vec_path) print("✅ Word2Vec 模型训练完成并保存。") def sentence_to_vec(self, sentence): """修复空向量问题""" tokens = preprocess(sentence).split() if not tokens: return np.zeros(100) # 默认向量大小 if self.word2vec_model: vecs = [self.word2vec_model.wv[w] for w in tokens if w in self.word2vec_model.wv] return np.mean(vecs, axis=0) if vecs else np.zeros(self.word2vec_model.vector_size) else: vec = self.tfidf_vectorizer.transform([preprocess(sentence)]).toarray()[0] return vec def build_model(self, epochs=10, batch_size=128, lr=1e-3): # 创建数据集 full_dataset = QADataset(self.qa_pairs, self.tfidf_vectorizer, negative_ratio=self.negative_ratio) # 划分训练集/验证集 train_size = int(len(full_dataset) * 0.8) val_size = len(full_dataset) - train_size train_dataset, val_dataset = random_split(full_dataset, [train_size, val_size]) # 创建数据加载器 train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=2) val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False, num_workers=2) # 初始化模型 sample_input, _ = full_dataset[0] input_dim = sample_input.shape[0] self.semantic_model = SemanticMatchModel(input_dim) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") self.semantic_model.to(device) criterion = nn.BCELoss() optimizer = optim.Adam(self.semantic_model.parameters(), lr=lr) scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'max', patience=2, factor=0.5) # 训练模型 best_val_acc = 0.0 print("\n开始模型训练...") start_time = time.time() for epoch in range(epochs): self.semantic_model.train() total_loss, total_correct, total_samples = 0.0, 0, 0 for X_batch, y_batch in tqdm(train_loader, desc=f"Epoch {epoch + 1}/{epochs} - 训练中"): X_batch, y_batch = X_batch.to(device), y_batch.to(device) optimizer.zero_grad() outputs = self.semantic_model(X_batch).squeeze() loss = criterion(outputs, y_batch) loss.backward() optimizer.step() total_loss += loss.item() * len(y_batch) preds = (outputs >= 0.5).float() total_correct += (preds == y_batch).sum().item() total_samples += len(y_batch) train_loss = total_loss / total_samples train_acc = total_correct / total_samples # 验证阶段 self.semantic_model.eval() val_loss, val_correct, val_samples = 0.0, 0, 0 with torch.no_grad(): for X_val, y_val in val_loader: X_val, y_val = X_val.to(device), y_val.to(device) outputs_val = self.semantic_model(X_val).squeeze() loss_val = criterion(outputs_val, y_val) val_loss += loss_val.item() * len(y_val) preds_val = (outputs_val >= 0.5).float() val_correct += (preds_val == y_val).sum().item() val_samples += len(y_val) val_loss /= val_samples val_acc = val_correct / val_samples # 更新学习率 scheduler.step(val_acc) print(f"Epoch [{epoch + 1}/{epochs}] | " f"Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.4f} | " f"Val Loss: {val_loss:.4f}, Val Acc: {val_acc:.4f}") # 保存最优模型 if val_acc > best_val_acc: best_val_acc = val_acc model_path = os.path.join(self.model_dir, 'semantic_match_model.pth') torch.save(self.semantic_model.state_dict(), model_path) print(f"✅ 新的最优模型已保存 (Val Acc: {best_val_acc:.4f})") end_time = time.time() print(f"\n训练完成,共耗时 {end_time - start_time:.2f} 秒。") # 加载最优模型权重 model_path = os.path.join(self.model_dir, 'semantic_match_model.pth') self.semantic_model.load_state_dict(torch.load(model_path, map_location=device)) self.semantic_model.eval() def load_model(self): """加载训练好的语义匹配模型""" input_dim = self.tfidf_matrix.shape[1] * 2 model_path = os.path.join(self.model_dir, 'semantic_match_model.pth') self.semantic_model = SemanticMatchModel(input_dim) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") self.semantic_model.load_state_dict(torch.load(model_path, map_location=device)) self.semantic_model.to(device) self.semantic_model.eval() print("✅ 语义匹配模型加载完成。") def retrieve(self, query, semantic_topk=100): # 粗检 query_tfidf = self.tfidf_vectorizer.transform([preprocess(query)]).toarray()[0] tfidf_scores = cosine_similarity([query_tfidf], self.tfidf_matrix).flatten() query_sent_vec = self.sentence_to_vec(query) sent_vecs = np.array([self.sentence_to_vec(q) for q in self.q_texts]) sent_scores = cosine_similarity([query_sent_vec], sent_vecs).flatten() # 归一化句子向量相似度到[0,1] sent_scores = (sent_scores + 1) / 2 sim_scores = tfidf_scores + sent_scores # 确保有足够的数据 if len(sim_scores) == 0: return ("抱歉,知识库中没有找到相关信息。", 0.0) topk_indices = np.argpartition(sim_scores, -semantic_topk)[-semantic_topk:] topk_indices = topk_indices[np.argsort(sim_scores[topk_indices])[::-1]] # 精检 if self.semantic_model: device = next(self.semantic_model.parameters()).device with torch.no_grad(): batch_inputs = [] for i in topk_indices: q = preprocess(self.q_texts[i]) a = preprocess(self.a_texts[i]) q_vec = self.tfidf_vectorizer.transform([q]).toarray()[0] a_vec = self.tfidf_vectorizer.transform([a]).toarray()[0] pair_input = np.concatenate((q_vec, a_vec)) batch_inputs.append(pair_input) if batch_inputs: batch_inputs = torch.tensor(np.stack(batch_inputs), dtype=torch.float32).to(device) batch_scores = self.semantic_model(batch_inputs).squeeze().cpu().numpy() semantic_scores = batch_scores else: semantic_scores = np.zeros(len(topk_indices)) # 综合得分(添加归一化权重) coarse_scores = sim_scores[topk_indices] / 2.0 # 归一化到[0,1] final_scores = 0.3 * coarse_scores + 0.7 * semantic_scores best_idx_in_topk = np.argmax(final_scores) best_idx = topk_indices[best_idx_in_topk] return self.qa_pairs[best_idx], final_scores[best_idx_in_topk] else: best_idx = topk_indices[0] if topk_indices.size > 0 else 0 return self.qa_pairs[best_idx], sim_scores[best_idx] def recommend_similar(self, query, topk=3): """修复索引越界问题""" query_tfidf = self.tfidf_vectorizer.transform([preprocess(query)]).toarray()[0] scores = cosine_similarity([query_tfidf], self.tfidf_matrix).flatten() # 安全获取topk索引 if len(scores) == 0: return [] if len(scores) < topk: topk = len(scores) topk_idx = np.argpartition(scores, -topk)[-topk:] topk_idx = topk_idx[np.argsort(scores[topk_idx])[::-1]] return [(self.q_texts[i], self.a_texts[i]) for i in topk_idx] class FeedbackRecorder: def __init__(self, file_path='unanswered_questions.csv'): self.file_path = file_path if not os.path.exists(self.file_path): with open(self.file_path, 'w', newline='', encoding='utf-8') as f: import csv csv.writer(f).writerow(['time', 'question']) def record_question(self, question): with open(self.file_path, 'a', newline='', encoding='utf-8') as f: import csv writer = csv.writer(f) writer.writerow([datetime.now().isoformat(), question]) def main(): kb = KnowledgeBase( host='localhost', user='root', password='hy188747', database='ubuntu_qa', table='qa_pair', model_dir=r"D:\NLP-PT\PT4\model", negative_ratio=1.0 ) if input("是否重新训练语义匹配模型?(y/n): ").strip().lower() == 'y': kb.build_model( epochs=5, batch_size=128, lr=1e-3 ) recorder = FeedbackRecorder() print("\n🎯 智能知识问答系统已启动(输入'q'退出聊天)\n") while True: query = input("🧐 问题:") if query.strip().lower() == 'q': break try: result, score = kb.retrieve(query) if result: print(f"💡 回答:{result[1]}") print(f"📊 匹配信心分数: {score:.4f}\n") else: print("⚠ 没有找到合适的答案,已将你的问题记录下来。") recorder.record_question(query) print("🔥 相似问题推荐:") similar_questions = kb.recommend_similar(query, topk=3) for q, a in similar_questions: print(f"Q: {q}\nA: {a}\n") except Exception as e: print(f"❌ 检索过程中发生错误: {e}") if __name__ == "__main__": main()

txt

最新推荐

recommend-type

【地球科学与遥感】基于Google Earth Engine的哨兵2号数据分析:研究区域NDVI、LST及城市热岛效应评估系统设计

内容概要:本文档提供了一套完整的Python脚本,利用Google Earth Engine (GEE) API对哨兵2号卫星影像进行处理与分析。首先,导入必要的库(如ee、geemap、geopandas),并通过Google Drive加载GeoJSON文件定义研究区域。接着,对哨兵2号Harmonized数据进行预处理,包括云掩膜、日期筛选和区域过滤。然后,基于红波段和近红外波段计算归一化植被指数(NDVI),并进一步推算地表温度(LST)。最后,通过计算研究区域内的LST均值和标准差,构建标准化城市热岛指数(UHI)和城市热场变异指数(UTFVI),并将其可视化于交互式地图中。 适合人群:具备一定遥感和地理信息系统(GIS)基础知识的研究人员和技术人员,特别是从事环境监测、城市规划或气候变化相关领域的工作者。 使用场景及目标:① 对特定区域内的植被覆盖和地表温度进行动态监测;② 分析城市热岛效应及其空间分布特征;③ 辅助城市规划和环境管理决策,提高应对气候变化的能力。 阅读建议:此资源侧重于实际应用中的遥感数据分析流程,建议读者熟悉Python编程语言和GEE平台的基本操作,同时结合具体的科学问题来理解和实践代码中的各个步骤。在学习过程中应关注数据处理逻辑与方法论的应用,确保能够独立完成类似的数据分析任务。
recommend-type

2025二级建造师继续教育考试题库带有答案.docx

2025二级建造师继续教育考试题库带有答案.docx
recommend-type

sglj宫颈癌lkdgj lsakgj路上lsslagjlalsagj

sglj宫颈癌lkdgj lsakgj路上lsslagjlalsagj
recommend-type

17页无人机俯仰姿态保持模糊PID控制设计报告:'仿真模型与性能改善'

基于模糊PID控制的无人机俯仰姿态精确保持设计及其性能优化。首先,建立了一款固定翼无人机的状态空间数学模型,并基于传统PID控制方法设计了初步的俯仰姿态控制律。然而,针对常规PID控制在复杂环境下的局限性,文中引入了模糊自适应PID控制方法,实现了对无人机俯仰姿态更为精准和平稳的控制。通过仿真实验验证,模糊PID控制显著减少了俯仰角单位阶跃响应的调节时间与超调量,降低了俯仰角速率的峰值,从而提高了无人机的飞行性能和稳定性。 适合人群:从事无人机技术研发的专业人士、自动化控制领域的研究人员以及对智能控制算法感兴趣的学者。 使用场景及目标:适用于需要提升无人机飞行稳定性和性能的研究项目,旨在解决复杂环境中无人机姿态控制的问题,提供一种有效的解决方案。 其他说明:文中还讨论了未来智能控制算法在无人机领域的潜在应用和发展方向,强调了模糊控制、神经网络控制等技术的重要性和前景。
recommend-type

Typora下载问题解决:资源安装包实测可用

### 知识点:Typora下载与安装问题解决 #### 1. Typora 简介 Typora 是一款流行的轻量级Markdown编辑器,它将实时预览功能和源代码编辑结合在一起,为用户提供了一个简洁高效的写作环境。由于其独特的设计和出色的用户体验,Typora 迅速在开发者和内容创作者之间获得了普及。 #### 2. Markdown 简介 Markdown 是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档,然后转换成有效的XHTML(或者HTML)文档。Markdown 被广泛用于编写 README 文件、撰写文章、创建富文本内容等。其特点在于简化了传统的排版语法,让写作更加专注于内容本身。 #### 3. Typora 的特点和优势 - **所见即所得编辑器**:Typora 结合了传统Markdown编辑器和富文本编辑器的优点,使得用户在编写文档时可以直接看到最终效果。 - **跨平台兼容性**:Typora 支持Windows、macOS以及Linux等多个操作系统。 - **简洁的界面**:它拥有简洁的用户界面,没有复杂的菜单,这有助于减少分心,专注于内容创作。 - **即时预览**:Typora 提供即时预览功能,用户可以立即看到其标记语法对应的视觉效果。 - **集成度高**:支持插入图片、代码块、表格、数学公式等多种格式。 - **扩展性**:支持多种主题和插件,可以进一步增强其功能。 #### 4. 关于标题:“关于Typora下载找不到资源” 当用户在寻找Typora的下载资源时,可能会遇到找不到官方下载链接或被错误资源误导的问题。这可能是由于网络环境限制、搜索关键词不当或者不正确的网站导航等原因导致的。为了解决这个问题,重要的是要知道如何辨别官方下载渠道,以及如何查找和验证可靠的资源。 #### 5. 官方资源的识别和下载 - **访问官方网站**:访问 Typora 的官方网站(https://typora.io/)获取最新版本的下载信息。官方网站是获取软件的最安全和最可靠的方式。 - **下载安装包**:官方网站通常会提供最新版本的安装包下载链接,例如,在此案例中,压缩包子文件名列表中的 typora-setup-x64-0.9.49.exe 对应了 Typora 的一个版本号为 0.9.49 的安装程序,适用于64位Windows系统。 - **检查版本更新**:在安装之前,用户应当确认是否是当前最新版本。如果不是,可从官方网站下载最新版本。 #### 6. 安装包文件名称解析 文件名 typora-setup-x64-0.9.49.exe 中的各部分含义: - **typora**:指的是要安装的软件名。 - **setup**:通常表示这是一个安装程序。 - **x64**:表示这个安装程序支持64位系统架构。 - **0.9.49**:表示这个版本号,用户可以通过这个版本号了解其更新历史和功能改进情况。 #### 7. 实测完成 “实测完成”这一描述表明此文件已经过测试,并确认可以正常下载和安装。实测的流程包括下载安装包、运行安装程序、完成安装以及验证软件功能是否正常。 #### 8. 安装流程详解 1. **下载**:从官方网站下载对应操作系统版本的 Typora 安装包。 2. **运行安装程序**:双击下载的安装程序文件(例如 typora-setup-x64-0.9.49.exe)。 3. **安装向导**:安装向导启动后,遵循提示完成安装。可能包含选择安装路径、接受许可协议、选择开始菜单文件夹等步骤。 4. **完成安装**:完成安装向导后,可能需要重启电脑以完成安装。 5. **验证安装**:启动 Typora 程序,检查软件是否能够正常打开,并确保可以正常使用Markdown编辑功能。 #### 9. 常见问题及解决方案 - **找不到下载资源**:确保访问官方网站或使用正规的软件分发平台获取资源。 - **安装程序无法运行**:检查文件是否有损坏,重新下载安装包。确认系统环境满足安装需求,如操作系统版本兼容性、运行库等。 - **软件无法打开**:尝试以管理员权限运行 Typora,或检查是否有系统安全软件阻止其运行。 - **功能异常或错误**:检查是否有可用的软件更新,或者查看 Typora 官方论坛获取帮助。 #### 10. Typora 的未来展望 由于 Typora 不断更新迭代,功能和用户界面可能会有所改变,包括对新特性的支持和旧特性的优化。同时,开发者社区也在不断地为 Typora 开发新的主题和插件,以提供更加丰富的写作体验和扩展功能。用户应定期访问官方网站或关注官方消息,以便获取最新动态和软件更新。 通过以上介绍和问题解答,用户应该可以更好地理解 Typora 的下载与安装过程,并在遇到相关问题时快速找到解决方法,从而顺利使用这款强大的Markdown编辑器。
recommend-type

网络嗅探器实战进阶:掌握高效数据捕获与准确分析的6大策略

# 1. 网络嗅探器基础原理与工具介绍 网络嗅探器,或称为网络分析器、包分析器,是一种用于捕获网络中的数据包并分析其内容的工具。它们通过直接连接到网络上,读取传输中的数据包信息,为网络安全、故障排除和网络性
recommend-type

system verilog task中用宏定义传参

<think>好的,用户现在想了解如何在SystemVerilog中使用宏定义向task传递参数。之前我已经回答了C/C++中宏定义传参的方法,现在需要迁移到SystemVerilog,同时结合用户提供的引用内容。 首先,我需要回忆SystemVerilog中宏的基本语法,确认是否与C/C++类似。SystemVerilog确实支持`define宏,带参数的形式应该也是类似的。用户提供的引用中提到`__FILE__`和`__LINE__`,这些可能和调试有关,所以可能需要考虑在宏中加入这些信息来帮助调试。 接下来,用户的问题是关于如何通过宏向task传参。这里的task应该是指System
recommend-type

Java开发的Help GUI 1.1源码:可视化组件库详解

在分析给定文件信息后,可以提取出如下知识点: 首先,标题中提到了“基于java的开发源码-帮助视图组件库 Help GUI 1.1源代码.zip”,这说明文件包含了一个Java开发的开源项目,该库被命名为Help GUI,版本为1.1。在此基础上,我们可以讨论以下几个方面: 1. Java开发: - Java是一种广泛使用的面向对象的编程语言,它具有跨平台的特性,即“一次编写,到处运行”的能力。Java通过Java虚拟机(JVM)来实现跨平台运行。 - Java的开发环境一般需要配置Java开发工具包(JDK)和集成开发环境(IDE),如Eclipse、IntelliJ IDEA或PyCharm。 - Java支持多线程编程,拥有丰富的类库和框架,如Spring、Hibernate等,用以简化开发流程。 - Java在企业级应用、移动开发(Android)、桌面应用和服务器端应用中都有广泛的应用。 2. 开源项目: - 开源项目是指源代码公开的软件项目,通常遵循特定的开源许可协议,如GPL、LGPL、Apache License等。 - 开源项目的优势在于可自由使用、修改和分发代码,能够促进技术的交流和创新。 - 通过参与开源项目,开发者可以提高自身的技术水平,贡献代码以回馈社区。 3. 组件库Help GUI 1.1: - Help GUI可能是一个为开发者提供的图形用户界面(GUI)组件库,用于简化Java桌面应用的帮助视图创建。 - 组件库一般会包含一系列预制的用户界面组件,例如按钮、文本框、列表框、对话框等,以帮助快速构建用户界面。 - 版本1.1表明这是组件库的一个更新版本,通常新版本会增加新的特性、修复bug、优化性能。 4. PyCharm配置Python环境: - 这部分描述似乎与主标题无关,但其可能涉及PyCharm这一IDE的使用。 - PyCharm是专为Python语言开发的IDE,但也可以配置Java开发环境。 - 在配置Python环境时,需要安装Python解释器,并设置相关的路径、环境变量等。 - PyCharm提供了代码高亮、代码自动完成、版本控制等功能,能够提升开发效率。 由于【压缩包子文件的文件名称列表】中只有一个“codefans.net”,这可能是一个网站地址,但没有提供足够的信息来推断与上述Java项目或组件库直接相关的内容。 综上所述,文件描述了一个基于Java的开源组件库Help GUI 1.1,该组件库用于帮助开发者创建帮助视图,且暗示了PyCharm这一IDE的使用。通过探讨Java开发、开源项目、组件库和IDE配置等知识点,可以更好地理解文件所指的项目背景和应用场景。
recommend-type

网络嗅探器全攻略:从入门到精通的15大技巧与实践案例

# 1. 网络嗅探器基础与重要性 在数字化的世界中,网络嗅探器是IT专业人员的重要工具,它允许我们监视和分析经过网络的数据包。本章将带您了解网络嗅探器的基本概念及其在网络安全和性能监控中的关键作用。 ## 网络嗅探器概述 网络嗅探器,通常被称为“抓包工具”或“协议分析器”,是一种可以监听、记录和分析网络流量的程序或设备。它们在排除网络问题、进行安全审计和协议分析时发挥着重要作用。 ##
recommend-type

RTL8720DN-VA1-CG后面的VA1-CG是什么意思

<think>嗯,用户这次的问题转向了具体的芯片型号解析,询问RTL8720DN-VA1-CG后缀的含义。这属于硬件标识领域的专业问题,需要结合芯片命名规则和行业惯例来分析。 从用户提问方式看,ta应该具备一定技术背景,可能是电子工程师或物联网开发者,正在做物料选型或故障排查。用户特意强调"参考站内引用"但实际没有引用源,说明需要权威解释而非普通科普。之前讨论Wi-Fi频段差异时用户表现出对技术参数的敏感,这次提问同样注重细节标识。 关于这个型号后缀,需要拆解三部分分析: VA1通常代表芯片修订版本(revision),比如初版叫VA0,改进版叫VA1。CG后缀可能有多种含义:最常见的是封